• 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 "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