]> granicus.if.org Git - esp-idf/blob - components/bt/bluedroid/stack/sdp/sdp_main.c
component/bt: add new demo for Bluetooth SDP client
[esp-idf] / components / bt / bluedroid / stack / sdp / sdp_main.c
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
50 tSDP_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 /********************************************************************************/
56 static void sdp_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm,
57                              UINT8 l2cap_id);
58 static void sdp_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
59 static void sdp_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
60 static void sdp_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed);
61 static void sdp_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg);
62
63 #if SDP_CLIENT_ENABLED == TRUE
64 static void sdp_connect_cfm (UINT16 l2cap_cid, UINT16 result);
65 static 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 *******************************************************************************/
81 void 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\n");
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\n");
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\n");
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 *******************************************************************************/
150 UINT16 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 *******************************************************************************/
172 static 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\n",
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\n", 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 *******************************************************************************/
230 static 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\n", 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\n",
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\n", p_ccb->connection_id);
267     }
268     else
269     {
270         SDP_TRACE_WARNING ("SDP - Rcvd conn cnf with error: 0x%x  CID 0x%x\n", 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 *******************************************************************************/
308 static 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\n", 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\n");
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\n");
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\n", 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\n", 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 *******************************************************************************/
402 static 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\n", 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\n", 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 *******************************************************************************/
460 static 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\n", 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\n", 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 *******************************************************************************/
503 static 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\n",
520                                 p_ccb->con_state, l2cap_cid);
521         }
522     }
523     else
524     {
525         SDP_TRACE_WARNING ("SDP - Rcvd L2CAP data, unknown CID: 0x%x\n", 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 *******************************************************************************/
543 tCONN_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\n");
552         return (NULL);
553     }
554
555     SDP_TRACE_EVENT ("SDP - Originate started\n");
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     cid = L2CA_ConnectReq (SDP_PSM, p_bd_addr);
567
568     /* Check if L2CAP started the connection process */
569     if (cid != 0)
570     {
571         p_ccb->connection_id = cid;
572
573         return (p_ccb);
574     }
575     else
576     {
577         SDP_TRACE_WARNING ("SDP - Originate failed\n");
578         sdpu_release_ccb (p_ccb);
579         return (NULL);
580     }
581 }
582
583 /*******************************************************************************
584 **
585 ** Function         sdp_disconnect
586 **
587 ** Description      This function disconnects a connection.
588 **
589 ** Returns          void
590 **
591 *******************************************************************************/
592 void sdp_disconnect (tCONN_CB*p_ccb, UINT16 reason)
593 {
594 #if (defined(SDP_BROWSE_PLUS) && SDP_BROWSE_PLUS == TRUE)
595     /* If we are browsing for multiple UUIDs ... */
596     if ((p_ccb->con_state == SDP_STATE_CONNECTED)
597      && (p_ccb->con_flags & SDP_FLAGS_IS_ORIG)
598      && ((reason == SDP_SUCCESS) || (reason == SDP_NO_RECS_MATCH)))
599     {
600         /* If the browse found something, do no more searching */
601         if ((p_ccb->cur_uuid_idx == 0) && (p_ccb->p_db->p_first_rec))
602             p_ccb->cur_uuid_idx = p_ccb->p_db->num_uuid_filters;
603
604         while (++p_ccb->cur_uuid_idx < p_ccb->p_db->num_uuid_filters)
605         {
606             /* Check we have not already found the UUID (maybe through browse) */
607             if ((p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx].len == 2)
608                 && (SDP_FindServiceInDb (p_ccb->p_db,
609                         p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx].uu.uuid16,
610                         NULL)))
611                 continue;
612
613             if ((p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx].len > 2)
614                 && (SDP_FindServiceUUIDInDb (p_ccb->p_db,
615                         &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx], NULL)))
616                 continue;
617
618             p_ccb->cur_handle = 0;
619
620             SDP_TRACE_EVENT ("SDP - looking for for more,  CID: 0x%x\n",
621                               p_ccb->connection_id);
622
623             sdp_disc_connected (p_ccb);
624             return;
625         }
626     }
627
628     if ((reason == SDP_NO_RECS_MATCH) && (p_ccb->p_db->p_first_rec))
629         reason = SDP_SUCCESS;
630
631 #endif
632
633     SDP_TRACE_EVENT ("SDP - disconnect  CID: 0x%x\n", p_ccb->connection_id);
634
635     /* Check if we have a connection ID */
636     if (p_ccb->connection_id != 0)
637     {
638         L2CA_DisconnectReq (p_ccb->connection_id);
639         p_ccb->disconnect_reason = reason;
640     }
641
642     /* If at setup state, we may not get callback ind from L2CAP */
643     /* Call user callback immediately */
644     if (p_ccb->con_state == SDP_STATE_CONN_SETUP)
645     {
646         /* Tell the user if he has a callback */
647         if (p_ccb->p_cb)
648             (*p_ccb->p_cb) (reason);
649         else if (p_ccb->p_cb2)
650             (*p_ccb->p_cb2) (reason, p_ccb->user_data);
651
652         sdpu_release_ccb (p_ccb);
653     }
654
655 }
656
657 /*******************************************************************************
658 **
659 ** Function         sdp_disconnect_cfm
660 **
661 ** Description      This function handles a disconnect confirm event from L2CAP.
662 **
663 ** Returns          void
664 **
665 *******************************************************************************/
666 static void sdp_disconnect_cfm (UINT16 l2cap_cid, UINT16 result)
667 {
668     tCONN_CB    *p_ccb;
669     UNUSED(result);
670
671     /* Find CCB based on CID */
672     if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL)
673     {
674         SDP_TRACE_WARNING ("SDP - Rcvd L2CAP disc cfm, unknown CID: 0x%x\n", l2cap_cid);
675         return;
676     }
677
678     SDP_TRACE_EVENT ("SDP - Rcvd L2CAP disc cfm, CID: 0x%x, rsn %d\n", l2cap_cid, p_ccb->disconnect_reason);
679     /* Tell the user if he has a callback */
680     if (p_ccb->p_cb)
681         (*p_ccb->p_cb) (p_ccb->disconnect_reason);
682     else if (p_ccb->p_cb2)
683         (*p_ccb->p_cb2) (p_ccb->disconnect_reason, p_ccb->user_data);
684
685
686     sdpu_release_ccb (p_ccb);
687 }
688
689 #endif  /* SDP_CLIENT_ENABLED == TRUE */
690
691 /*******************************************************************************
692 **
693 ** Function         sdp_conn_timeout
694 **
695 ** Description      This function processes a timeout. Currently, we simply send
696 **                  a disconnect request to L2CAP.
697 **
698 ** Returns          void
699 **
700 *******************************************************************************/
701 void sdp_conn_timeout (tCONN_CB*p_ccb)
702 {
703     SDP_TRACE_EVENT ("SDP - CCB timeout in state: %d  CID: 0x%x\n",
704                       p_ccb->con_state, p_ccb->connection_id);
705
706     L2CA_DisconnectReq (p_ccb->connection_id);
707 #if SDP_CLIENT_ENABLED == TRUE
708     /* Tell the user if he has a callback */
709     if (p_ccb->p_cb)
710         (*p_ccb->p_cb) (SDP_CONN_FAILED);
711     else if (p_ccb->p_cb2)
712         (*p_ccb->p_cb2) (SDP_CONN_FAILED, p_ccb->user_data);
713 #endif
714     sdpu_release_ccb (p_ccb);
715 }
716
717
718
719