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