• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
49 tSDP_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 /********************************************************************************/
55 static void sdp_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm,
56                              UINT8 l2cap_id);
57 static void sdp_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
58 static void sdp_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
59 static void sdp_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed);
60 static void sdp_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg);
61 
62 #if SDP_CLIENT_ENABLED == TRUE
63 static void sdp_connect_cfm (UINT16 l2cap_cid, UINT16 result);
64 static 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 *******************************************************************************/
sdp_init(void)80 void 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 *******************************************************************************/
sdp_set_max_attr_list_size(UINT16 max_size)149 UINT16 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 *******************************************************************************/
sdp_connect_ind(BD_ADDR bd_addr,UINT16 l2cap_cid,UINT16 psm,UINT8 l2cap_id)171 static 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 *******************************************************************************/
sdp_connect_cfm(UINT16 l2cap_cid,UINT16 result)228 static 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 *******************************************************************************/
sdp_config_ind(UINT16 l2cap_cid,tL2CAP_CFG_INFO * p_cfg)306 static 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 *******************************************************************************/
sdp_config_cfm(UINT16 l2cap_cid,tL2CAP_CFG_INFO * p_cfg)400 static 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 *******************************************************************************/
sdp_disconnect_ind(UINT16 l2cap_cid,BOOLEAN ack_needed)458 static 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 *******************************************************************************/
sdp_data_ind(UINT16 l2cap_cid,BT_HDR * p_msg)501 static 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 *******************************************************************************/
sdp_conn_originate(UINT8 * p_bd_addr)541 tCONN_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 *******************************************************************************/
sdp_disconnect(tCONN_CB * p_ccb,UINT16 reason)596 void 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 *******************************************************************************/
sdp_disconnect_cfm(UINT16 l2cap_cid,UINT16 result)671 static 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 *******************************************************************************/
sdp_conn_timeout(tCONN_CB * p_ccb)706 void 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