1 /******************************************************************************
2  *
3  *  Copyright (C) 2009-2013 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 #include "common/bt_target.h"
21 #include "common/bt_defs.h"
22 #include "stack/btu.h"
23 #include "gap_int.h"
24 #include "stack/l2cdefs.h"
25 #include "l2c_int.h"
26 #include <string.h>
27 #include "osi/mutex.h"
28 #include "osi/allocator.h"
29 
30 #if GAP_CONN_INCLUDED == TRUE
31 #include "btm_int.h"
32 
33 /********************************************************************************/
34 /*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
35 /********************************************************************************/
36 static void gap_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id);
37 static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result);
38 static void gap_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
39 static void gap_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
40 static void gap_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed);
41 static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg);
42 static void gap_congestion_ind (UINT16 lcid, BOOLEAN is_congested);
43 
44 static tGAP_CCB *gap_find_ccb_by_cid (UINT16 cid);
45 static tGAP_CCB *gap_find_ccb_by_handle (UINT16 handle);
46 static tGAP_CCB *gap_allocate_ccb (void);
47 static void      gap_release_ccb (tGAP_CCB *p_ccb);
48 
49 /*******************************************************************************
50 **
51 ** Function         gap_conn_init
52 **
53 ** Description      This function is called to initialize GAP connection management
54 **
55 ** Returns          void
56 **
57 *******************************************************************************/
gap_conn_init(void)58 void gap_conn_init (void)
59 {
60 #if ((defined AMP_INCLUDED) && (AMP_INCLUDED == TRUE))
61     gap_cb.conn.reg_info.pAMP_ConnectInd_Cb         = gap_connect_ind;
62     gap_cb.conn.reg_info.pAMP_ConnectCfm_Cb         = gap_connect_cfm;
63     gap_cb.conn.reg_info.pAMP_ConnectPnd_Cb         = NULL;
64     gap_cb.conn.reg_info.pAMP_ConfigInd_Cb          = gap_config_ind;
65     gap_cb.conn.reg_info.pAMP_ConfigCfm_Cb          = gap_config_cfm;
66     gap_cb.conn.reg_info.pAMP_DisconnectInd_Cb      = gap_disconnect_ind;
67     gap_cb.conn.reg_info.pAMP_DisconnectCfm_Cb      = NULL;
68     gap_cb.conn.reg_info.pAMP_QoSViolationInd_Cb    = NULL;
69     gap_cb.conn.reg_info.pAMP_DataInd_Cb            = gap_data_ind;
70     gap_cb.conn.reg_info.pAMP_CongestionStatus_Cb   = gap_congestion_ind;
71     gap_cb.conn.reg_info.pAMP_TxComplete_Cb         = NULL;
72     gap_cb.conn.reg_info.pAMP_MoveInd_Cb            = NULL;
73     gap_cb.conn.reg_info.pAMP_MoveRsp_Cb            = NULL;
74     gap_cb.conn.reg_info.pAMP_MoveCfm_Cb            = NULL; //gap_move_cfm
75     gap_cb.conn.reg_info.pAMP_MoveCfmRsp_Cb         = NULL; //gap_move_cfm_rsp
76 
77 #else
78     gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb       = gap_connect_ind;
79     gap_cb.conn.reg_info.pL2CA_ConnectCfm_Cb       = gap_connect_cfm;
80     gap_cb.conn.reg_info.pL2CA_ConnectPnd_Cb       = NULL;
81     gap_cb.conn.reg_info.pL2CA_ConfigInd_Cb        = gap_config_ind;
82     gap_cb.conn.reg_info.pL2CA_ConfigCfm_Cb        = gap_config_cfm;
83     gap_cb.conn.reg_info.pL2CA_DisconnectInd_Cb    = gap_disconnect_ind;
84     gap_cb.conn.reg_info.pL2CA_DisconnectCfm_Cb    = NULL;
85     gap_cb.conn.reg_info.pL2CA_QoSViolationInd_Cb  = NULL;
86     gap_cb.conn.reg_info.pL2CA_DataInd_Cb          = gap_data_ind;
87     gap_cb.conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind;
88     gap_cb.conn.reg_info.pL2CA_TxComplete_Cb       = NULL;
89 #endif
90 }
91 
92 
93 /*******************************************************************************
94 **
95 ** Function         GAP_ConnOpen
96 **
97 ** Description      This function is called to open an L2CAP connection.
98 **
99 ** Parameters:      is_server   - If TRUE, the connection is not created
100 **                                but put into a "listen" mode waiting for
101 **                                the remote side to connect.
102 **
103 **                  service_id  - Unique service ID from
104 **                                BTM_SEC_SERVICE_FIRST_EMPTY (6)
105 **                                to BTM_SEC_MAX_SERVICE_RECORDS (32)
106 **
107 **                  p_rem_bda   - Pointer to remote BD Address.
108 **                                If a server, and we don't care about the
109 **                                remote BD Address, then NULL should be passed.
110 **
111 **                  psm         - the PSM used for the connection
112 **
113 **                  p_config    - Optional pointer to configuration structure.
114 **                                If NULL, the default GAP configuration will
115 **                                be used.
116 **
117 **                  security    - security flags
118 **                  chan_mode_mask - (GAP_FCR_CHAN_OPT_BASIC, GAP_FCR_CHAN_OPT_ERTM,
119 **                                    GAP_FCR_CHAN_OPT_STREAM)
120 **
121 **                  p_cb        - Pointer to callback function for events.
122 **
123 ** Returns          handle of the connection if successful, else GAP_INVALID_HANDLE
124 **
125 *******************************************************************************/
GAP_ConnOpen(const char * p_serv_name,UINT8 service_id,BOOLEAN is_server,BD_ADDR p_rem_bda,UINT16 psm,tL2CAP_CFG_INFO * p_cfg,tL2CAP_ERTM_INFO * ertm_info,UINT16 security,UINT8 chan_mode_mask,tGAP_CONN_CALLBACK * p_cb)126 UINT16 GAP_ConnOpen (const char *p_serv_name, UINT8 service_id, BOOLEAN is_server,
127                      BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg,
128                      tL2CAP_ERTM_INFO *ertm_info, UINT16 security, UINT8 chan_mode_mask,
129                      tGAP_CONN_CALLBACK *p_cb)
130 {
131     tGAP_CCB    *p_ccb;
132     UINT16       cid;
133     //tBT_UUID    bt_uuid = {2, {GAP_PROTOCOL_ID}};
134 
135     GAP_TRACE_EVENT ("GAP_CONN - Open Request");
136 
137     /* Allocate a new CCB. Return if none available. */
138     if ((p_ccb = gap_allocate_ccb()) == NULL) {
139         return (GAP_INVALID_HANDLE);
140     }
141 
142     /* If caller specified a BD address, save it */
143     if (p_rem_bda) {
144         /* the bd addr is not BT_BD_ANY, then a bd address was specified */
145         if (memcmp (p_rem_bda, BT_BD_ANY, BD_ADDR_LEN)) {
146             p_ccb->rem_addr_specified = TRUE;
147         }
148 
149         memcpy (&p_ccb->rem_dev_address[0], p_rem_bda, BD_ADDR_LEN);
150     } else if (!is_server) {
151         /* remore addr is not specified and is not a server -> bad */
152         return (GAP_INVALID_HANDLE);
153     }
154 
155     /* A client MUST have specified a bd addr to connect with */
156     if (!p_ccb->rem_addr_specified && !is_server) {
157         gap_release_ccb (p_ccb);
158         GAP_TRACE_ERROR ("GAP ERROR: Client must specify a remote BD ADDR to connect to!");
159         return (GAP_INVALID_HANDLE);
160     }
161 
162     /* Check if configuration was specified */
163     if (p_cfg) {
164         p_ccb->cfg = *p_cfg;
165     }
166 
167     p_ccb->p_callback     = p_cb;
168 
169     /* If originator, use a dynamic PSM */
170 #if ((defined AMP_INCLUDED) && (AMP_INCLUDED == TRUE))
171     if (!is_server) {
172         gap_cb.conn.reg_info.pAMP_ConnectInd_Cb  = NULL;
173     } else {
174         gap_cb.conn.reg_info.pAMP_ConnectInd_Cb  = gap_connect_ind;
175     }
176 #else
177     if (!is_server) {
178         gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = NULL;
179     } else {
180         gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
181     }
182 #endif
183 
184     /* Register the PSM with L2CAP */
185     if ((p_ccb->psm = L2CA_REGISTER (psm, &gap_cb.conn.reg_info,
186                                      AMP_AUTOSWITCH_ALLOWED | AMP_USE_AMP_IF_POSSIBLE)) == 0) {
187         GAP_TRACE_ERROR ("GAP_ConnOpen: Failure registering PSM 0x%04x", psm);
188         gap_release_ccb (p_ccb);
189         return (GAP_INVALID_HANDLE);
190     }
191 
192     /* Register with Security Manager for the specific security level */
193     p_ccb->service_id = service_id;
194     if (!BTM_SetSecurityLevel ((UINT8)!is_server, p_serv_name,
195                                p_ccb->service_id, security, p_ccb->psm, 0, 0)) {
196         GAP_TRACE_ERROR ("GAP_CONN - Security Error");
197         gap_release_ccb (p_ccb);
198         return (GAP_INVALID_HANDLE);
199     }
200 
201     /* Fill in eL2CAP parameter data */
202     if ( p_ccb->cfg.fcr_present ) {
203         if (ertm_info == NULL) {
204             p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode;
205             p_ccb->ertm_info.user_rx_buf_size = GAP_DATA_BUF_SIZE;
206             p_ccb->ertm_info.user_tx_buf_size = GAP_DATA_BUF_SIZE;
207             p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
208             p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
209         } else {
210             p_ccb->ertm_info = *ertm_info;
211         }
212     }
213 
214     /* optional FCR channel modes */
215     if (ertm_info != NULL) {
216         p_ccb->ertm_info.allowed_modes =
217             (chan_mode_mask) ? chan_mode_mask : (UINT8)L2CAP_FCR_CHAN_OPT_BASIC;
218     }
219 
220     if (is_server) {
221         p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */
222         p_ccb->con_state = GAP_CCB_STATE_LISTENING;
223         return (p_ccb->gap_handle);
224     } else {
225         /* We are the originator of this connection */
226         p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG;
227 
228         /* Transition to the next appropriate state, waiting for connection confirm. */
229         p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP;
230 
231         /* mark security done flag, when security is not required */
232         if ((security & (BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT) ) == 0) {
233             p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
234         }
235 
236         /* Check if L2CAP started the connection process */
237         if (p_rem_bda && ((cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info, &bt_uuid)) != 0)) {
238             p_ccb->connection_id = cid;
239             return (p_ccb->gap_handle);
240         } else {
241             gap_release_ccb (p_ccb);
242             return (GAP_INVALID_HANDLE);
243         }
244     }
245 }
246 
247 
248 /*******************************************************************************
249 **
250 ** Function         GAP_ConnClose
251 **
252 ** Description      This function is called to close a connection.
253 **
254 ** Parameters:      handle      - Handle of the connection returned by GAP_ConnOpen
255 **
256 ** Returns          BT_PASS             - closed OK
257 **                  GAP_ERR_BAD_HANDLE  - invalid handle
258 **
259 *******************************************************************************/
GAP_ConnClose(UINT16 gap_handle)260 UINT16 GAP_ConnClose (UINT16 gap_handle)
261 {
262     tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
263 
264     GAP_TRACE_EVENT ("GAP_CONN - close  handle: 0x%x", gap_handle);
265 
266     if (p_ccb) {
267         /* Check if we have a connection ID */
268         if (p_ccb->con_state != GAP_CCB_STATE_LISTENING) {
269             L2CA_DISCONNECT_REQ (p_ccb->connection_id);
270         }
271 
272         gap_release_ccb (p_ccb);
273 
274         return (BT_PASS);
275     }
276 
277     return (GAP_ERR_BAD_HANDLE);
278 }
279 
280 
281 
282 /*******************************************************************************
283 **
284 ** Function         GAP_ConnReadData
285 **
286 ** Description      Normally not GKI aware application will call this function
287 **                  after receiving GAP_EVT_RXDATA event.
288 **
289 ** Parameters:      handle      - Handle of the connection returned in the Open
290 **                  p_data      - Data area
291 **                  max_len     - Byte count requested
292 **                  p_len       - Byte count received
293 **
294 ** Returns          BT_PASS             - data read
295 **                  GAP_ERR_BAD_HANDLE  - invalid handle
296 **                  GAP_NO_DATA_AVAIL   - no data available
297 **
298 *******************************************************************************/
GAP_ConnReadData(UINT16 gap_handle,UINT8 * p_data,UINT16 max_len,UINT16 * p_len)299 UINT16 GAP_ConnReadData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT16 *p_len)
300 {
301     tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
302     UINT16      copy_len;
303 
304     if (!p_ccb) {
305         return (GAP_ERR_BAD_HANDLE);
306     }
307 
308     *p_len = 0;
309 
310     if (fixed_queue_is_empty(p_ccb->rx_queue)) {
311         return (GAP_NO_DATA_AVAIL);
312 	}
313 
314     osi_mutex_global_lock();
315 
316     while (max_len) {
317         BT_HDR *p_buf = fixed_queue_try_peek_first(p_ccb->rx_queue);
318         if (p_buf == NULL) {
319             break;
320 		}
321 
322         copy_len = (p_buf->len > max_len)?max_len:p_buf->len;
323         max_len -= copy_len;
324         *p_len  += copy_len;
325         if (p_data) {
326             memcpy (p_data, (UINT8 *)(p_buf + 1) + p_buf->offset, copy_len);
327             p_data += copy_len;
328         }
329 
330         if (p_buf->len > copy_len) {
331             p_buf->offset += copy_len;
332             p_buf->len    -= copy_len;
333             break;
334         }
335         osi_free(fixed_queue_dequeue(p_ccb->rx_queue, 0));
336     }
337 
338     p_ccb->rx_queue_size -= *p_len;
339 
340     osi_mutex_global_unlock();
341 
342     GAP_TRACE_EVENT ("GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d",
343                      p_ccb->rx_queue_size, *p_len);
344 
345     return (BT_PASS);
346 }
347 
348 /*******************************************************************************
349 **
350 ** Function         GAP_GetRxQueueCnt
351 **
352 ** Description      This function return number of bytes on the rx queue.
353 **
354 ** Parameters:      handle     - Handle returned in the GAP_ConnOpen
355 **                  p_rx_queue_count - Pointer to return queue count in.
356 **
357 **
358 *******************************************************************************/
GAP_GetRxQueueCnt(UINT16 handle,UINT32 * p_rx_queue_count)359 int GAP_GetRxQueueCnt (UINT16 handle, UINT32 *p_rx_queue_count)
360 {
361     tGAP_CCB    *p_ccb;
362     int         rc = BT_PASS;
363 
364     /* Check that handle is valid */
365     if (handle < GAP_MAX_CONNECTIONS) {
366         p_ccb = &gap_cb.conn.ccb_pool[handle];
367 
368         if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
369             *p_rx_queue_count = p_ccb->rx_queue_size;
370         } else {
371             rc = GAP_INVALID_HANDLE;
372         }
373     } else {
374         rc = GAP_INVALID_HANDLE;
375     }
376 
377     GAP_TRACE_EVENT ("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d",
378                      rc , *p_rx_queue_count);
379 
380     return (rc);
381 }
382 
383 /*******************************************************************************
384 **
385 ** Function         GAP_ConnBTRead
386 **
387 ** Description      Bluetooth aware applications will call this function after receiving
388 **                  GAP_EVT_RXDATA event.
389 **
390 ** Parameters:      handle      - Handle of the connection returned in the Open
391 **                  pp_buf      - pointer to address of buffer with data,
392 **
393 ** Returns          BT_PASS             - data read
394 **                  GAP_ERR_BAD_HANDLE  - invalid handle
395 **                  GAP_NO_DATA_AVAIL   - no data available
396 **
397 *******************************************************************************/
GAP_ConnBTRead(UINT16 gap_handle,BT_HDR ** pp_buf)398 UINT16 GAP_ConnBTRead (UINT16 gap_handle, BT_HDR **pp_buf)
399 {
400     tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
401     BT_HDR      *p_buf;
402 
403     if (!p_ccb) {
404         return (GAP_ERR_BAD_HANDLE);
405     }
406 
407     p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->rx_queue, 0);
408 
409     if (p_buf) {
410         *pp_buf = p_buf;
411 
412         p_ccb->rx_queue_size -= p_buf->len;
413         return (BT_PASS);
414     } else {
415         *pp_buf = NULL;
416         return (GAP_NO_DATA_AVAIL);
417     }
418 }
419 
420 
421 /*******************************************************************************
422 **
423 ** Function         GAP_ConnBTWrite
424 **
425 ** Description      Bluetooth Aware applications can call this function to write data.
426 **
427 ** Parameters:      handle      - Handle of the connection returned in the Open
428 **                  p_buf      - pointer to address of buffer with data,
429 **
430 ** Returns          BT_PASS                 - data read
431 **                  GAP_ERR_BAD_HANDLE      - invalid handle
432 **                  GAP_ERR_BAD_STATE       - connection not established
433 **                  GAP_INVALID_BUF_OFFSET  - buffer offset is invalid
434 *******************************************************************************/
GAP_ConnBTWrite(UINT16 gap_handle,BT_HDR * p_buf)435 UINT16 GAP_ConnBTWrite (UINT16 gap_handle, BT_HDR *p_buf)
436 {
437     tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
438 
439     if (!p_ccb) {
440         osi_free (p_buf);
441         return (GAP_ERR_BAD_HANDLE);
442     }
443 
444     if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) {
445         osi_free (p_buf);
446         return (GAP_ERR_BAD_STATE);
447     }
448 
449     if (p_buf->offset < L2CAP_MIN_OFFSET) {
450         osi_free (p_buf);
451         return (GAP_ERR_BUF_OFFSET);
452     }
453 
454     fixed_queue_enqueue(p_ccb->tx_queue, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
455 
456     if (p_ccb->is_congested) {
457         return (BT_PASS);
458     }
459 
460     /* Send the buffer through L2CAP */
461 #if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
462     gap_send_event (gap_handle);
463 #else
464     while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->tx_queue, 0)) != NULL) {
465         UINT8 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
466 
467         if (status == L2CAP_DW_CONGESTED) {
468             p_ccb->is_congested = TRUE;
469             break;
470         } else if (status != L2CAP_DW_SUCCESS) {
471             return (GAP_ERR_BAD_STATE);
472         }
473     }
474 #endif
475     return (BT_PASS);
476 }
477 
478 
479 /*******************************************************************************
480 **
481 ** Function         GAP_ConnWriteData
482 **
483 ** Description      Normally not GKI aware application will call this function
484 **                  to send data to the connection.
485 **
486 ** Parameters:      handle      - Handle of the connection returned in the Open
487 **                  p_data      - Data area
488 **                  max_len     - Byte count requested
489 **                  p_len       - Byte count received
490 **
491 ** Returns          BT_PASS                 - data read
492 **                  GAP_ERR_BAD_HANDLE      - invalid handle
493 **                  GAP_ERR_BAD_STATE       - connection not established
494 **                  GAP_CONGESTION          - system is congested
495 **
496 *******************************************************************************/
GAP_ConnWriteData(UINT16 gap_handle,UINT8 * p_data,UINT16 max_len,UINT16 * p_len)497 UINT16 GAP_ConnWriteData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT16 *p_len)
498 {
499     tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
500     BT_HDR     *p_buf;
501 
502     *p_len = 0;
503 
504     if (!p_ccb) {
505         return (GAP_ERR_BAD_HANDLE);
506     }
507 
508     if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) {
509         return (GAP_ERR_BAD_STATE);
510     }
511 
512     while (max_len) {
513         if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
514             if ((p_buf = (BT_HDR *)osi_malloc(L2CAP_FCR_ERTM_BUF_SIZE)) == NULL) {
515                 return (GAP_ERR_CONGESTED);
516             }
517         } else {
518             if ((p_buf = (BT_HDR *)osi_malloc(GAP_DATA_BUF_SIZE)) == NULL) {
519                 return (GAP_ERR_CONGESTED);
520             }
521         }
522 
523         p_buf->offset = L2CAP_MIN_OFFSET;
524         p_buf->len = (p_ccb->rem_mtu_size < max_len) ? p_ccb->rem_mtu_size : max_len;
525         p_buf->event = BT_EVT_TO_BTU_SP_DATA;
526 
527         memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, p_buf->len);
528 
529         *p_len  += p_buf->len;
530         max_len -= p_buf->len;
531         p_data  += p_buf->len;
532 
533         GAP_TRACE_EVENT ("GAP_WriteData %d bytes", p_buf->len);
534 
535         fixed_queue_enqueue(p_ccb->tx_queue, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
536     }
537 
538     if (p_ccb->is_congested) {
539         return (BT_PASS);
540     }
541 
542     /* Send the buffer through L2CAP */
543 #if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
544     gap_send_event (gap_handle);
545 #else
546     while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->tx_queue, 0)) != NULL)
547     {
548         UINT8 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
549 
550         if (status == L2CAP_DW_CONGESTED) {
551             p_ccb->is_congested = TRUE;
552             break;
553         } else if (status != L2CAP_DW_SUCCESS) {
554             return (GAP_ERR_BAD_STATE);
555         }
556     }
557 #endif
558     return (BT_PASS);
559 }
560 
561 /*******************************************************************************
562 **
563 ** Function         GAP_ConnReconfig
564 **
565 ** Description      Applications can call this function to reconfigure the connection.
566 **
567 ** Parameters:      handle      - Handle of the connection
568 **                  p_cfg       - Pointer to new configuration
569 **
570 ** Returns          BT_PASS                 - config process started
571 **                  GAP_ERR_BAD_HANDLE      - invalid handle
572 **
573 *******************************************************************************/
GAP_ConnReconfig(UINT16 gap_handle,tL2CAP_CFG_INFO * p_cfg)574 UINT16 GAP_ConnReconfig (UINT16 gap_handle, tL2CAP_CFG_INFO *p_cfg)
575 {
576     tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
577 
578     if (!p_ccb) {
579         return (GAP_ERR_BAD_HANDLE);
580     }
581 
582     p_ccb->cfg = *p_cfg;
583 
584     if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
585         L2CA_CONFIG_REQ (p_ccb->connection_id, p_cfg);
586     }
587 
588     return (BT_PASS);
589 }
590 
591 
592 
593 /*******************************************************************************
594 **
595 ** Function         GAP_ConnSetIdleTimeout
596 **
597 ** Description      Higher layers call this function to set the idle timeout for
598 **                  a connection, or for all future connections. The "idle timeout"
599 **                  is the amount of time that a connection can remain up with
600 **                  no L2CAP channels on it. A timeout of zero means that the
601 **                  connection will be torn down immediately when the last channel
602 **                  is removed. A timeout of 0xFFFF means no timeout. Values are
603 **                  in seconds.
604 **
605 ** Parameters:      handle      - Handle of the connection
606 **                  timeout     - in secs
607 **                                0 = immediate disconnect when last channel is removed
608 **                                0xFFFF = no idle timeout
609 **
610 ** Returns          BT_PASS                 - config process started
611 **                  GAP_ERR_BAD_HANDLE      - invalid handle
612 **
613 *******************************************************************************/
GAP_ConnSetIdleTimeout(UINT16 gap_handle,UINT16 timeout)614 UINT16 GAP_ConnSetIdleTimeout (UINT16 gap_handle, UINT16 timeout)
615 {
616     tGAP_CCB    *p_ccb;
617 
618     if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL) {
619         return (GAP_ERR_BAD_HANDLE);
620     }
621 
622     if (L2CA_SetIdleTimeout (p_ccb->connection_id, timeout, FALSE)) {
623         return (BT_PASS);
624     } else {
625         return (GAP_ERR_BAD_HANDLE);
626     }
627 }
628 
629 
630 
631 /*******************************************************************************
632 **
633 ** Function         GAP_ConnGetRemoteAddr
634 **
635 ** Description      This function is called to get the remote BD address
636 **                  of a connection.
637 **
638 ** Parameters:      handle      - Handle of the connection returned by GAP_ConnOpen
639 **
640 ** Returns          BT_PASS             - closed OK
641 **                  GAP_ERR_BAD_HANDLE  - invalid handle
642 **
643 *******************************************************************************/
GAP_ConnGetRemoteAddr(UINT16 gap_handle)644 UINT8 *GAP_ConnGetRemoteAddr (UINT16 gap_handle)
645 {
646     tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
647 
648     GAP_TRACE_EVENT ("GAP_ConnGetRemoteAddr gap_handle = %d", gap_handle);
649 
650     if ((p_ccb) && (p_ccb->con_state > GAP_CCB_STATE_LISTENING)) {
651         GAP_TRACE_EVENT("GAP_ConnGetRemoteAddr bda :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", \
652                         p_ccb->rem_dev_address[0], p_ccb->rem_dev_address[1], p_ccb->rem_dev_address[2],
653                         p_ccb->rem_dev_address[3], p_ccb->rem_dev_address[4], p_ccb->rem_dev_address[5]);
654         return (p_ccb->rem_dev_address);
655     } else {
656         GAP_TRACE_EVENT ("GAP_ConnGetRemoteAddr return Error ");
657         return (NULL);
658     }
659 }
660 
661 
662 /*******************************************************************************
663 **
664 ** Function         GAP_ConnGetRemMtuSize
665 **
666 ** Description      Returns the remote device's MTU size
667 **
668 ** Parameters:      handle      - Handle of the connection
669 **
670 ** Returns          UINT16      - maximum size buffer that can be transmitted to the peer
671 **
672 *******************************************************************************/
GAP_ConnGetRemMtuSize(UINT16 gap_handle)673 UINT16 GAP_ConnGetRemMtuSize (UINT16 gap_handle)
674 {
675     tGAP_CCB    *p_ccb;
676 
677     if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL) {
678         return (0);
679     }
680 
681     return (p_ccb->rem_mtu_size);
682 }
683 
684 /*******************************************************************************
685 **
686 ** Function         GAP_ConnGetL2CAPCid
687 **
688 ** Description      Returns the L2CAP channel id
689 **
690 ** Parameters:      handle      - Handle of the connection
691 **
692 ** Returns          UINT16      - The L2CAP channel id
693 **                  0, if error
694 **
695 *******************************************************************************/
GAP_ConnGetL2CAPCid(UINT16 gap_handle)696 UINT16 GAP_ConnGetL2CAPCid (UINT16 gap_handle)
697 {
698     tGAP_CCB    *p_ccb;
699 
700     if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL) {
701         return (0);
702     }
703 
704     return (p_ccb->connection_id);
705 }
706 
707 
708 /*******************************************************************************
709 **
710 ** Function         gap_connect_ind
711 **
712 ** Description      This function handles an inbound connection indication
713 **                  from L2CAP. This is the case where we are acting as a
714 **                  server.
715 **
716 ** Returns          void
717 **
718 *******************************************************************************/
gap_connect_ind(BD_ADDR bd_addr,UINT16 l2cap_cid,UINT16 psm,UINT8 l2cap_id)719 static void gap_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id)
720 {
721     UINT16       xx;
722     tGAP_CCB     *p_ccb;
723     //tBT_UUID    bt_uuid = {2, {GAP_PROTOCOL_ID}};
724 
725     /* See if we have a CCB listening for the connection */
726     for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
727         if ((p_ccb->con_state == GAP_CCB_STATE_LISTENING)
728                 && (p_ccb->psm == psm)
729                 && ((p_ccb->rem_addr_specified == FALSE)
730                     || (!memcmp (bd_addr, p_ccb->rem_dev_address, BD_ADDR_LEN)))) {
731             break;
732         }
733     }
734 
735     if (xx == GAP_MAX_CONNECTIONS) {
736         GAP_TRACE_WARNING("*******");
737         GAP_TRACE_WARNING("WARNING: GAP Conn Indication for Unexpected Bd Addr...Disconnecting");
738         GAP_TRACE_WARNING("*******");
739 
740         /* Disconnect because it is an unexpected connection */
741         L2CA_DISCONNECT_REQ (l2cap_cid);
742         return;
743     }
744 
745     /* Transition to the next appropriate state, waiting for config setup. */
746     p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
747 
748     /* Save the BD Address and Channel ID. */
749     memcpy (&p_ccb->rem_dev_address[0], bd_addr, BD_ADDR_LEN);
750     p_ccb->connection_id = l2cap_cid;
751 
752     /* Send response to the L2CAP layer. */
753     L2CA_CONNECT_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->ertm_info, &bt_uuid);
754 
755     GAP_TRACE_EVENT("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x", p_ccb->connection_id);
756 
757     /* Send a Configuration Request. */
758     L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
759 }
760 
761 /*******************************************************************************
762 **
763 ** Function         gap_checks_con_flags
764 **
765 ** Description      This function processes the L2CAP configuration indication
766 **                  event.
767 **
768 ** Returns          void
769 **
770 *******************************************************************************/
gap_checks_con_flags(tGAP_CCB * p_ccb)771 static void gap_checks_con_flags (tGAP_CCB    *p_ccb)
772 {
773     GAP_TRACE_EVENT ("gap_checks_con_flags conn_flags:0x%x, ", p_ccb->con_flags);
774     /* if all the required con_flags are set, report the OPEN event now */
775     if ((p_ccb->con_flags & GAP_CCB_FLAGS_CONN_DONE) == GAP_CCB_FLAGS_CONN_DONE) {
776         p_ccb->con_state = GAP_CCB_STATE_CONNECTED;
777 
778         p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_OPENED);
779     }
780 }
781 
782 /*******************************************************************************
783 **
784 ** Function         gap_sec_check_complete
785 **
786 ** Description      The function called when Security Manager finishes
787 **                  verification of the service side connection
788 **
789 ** Returns          void
790 **
791 *******************************************************************************/
gap_sec_check_complete(BD_ADDR bd_addr,tBT_TRANSPORT transport,void * p_ref_data,UINT8 res)792 static void gap_sec_check_complete (BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res)
793 {
794     tGAP_CCB *p_ccb = (tGAP_CCB *)p_ref_data;
795     UNUSED(bd_addr);
796     UNUSED (transport);
797 
798     GAP_TRACE_EVENT ("gap_sec_check_complete conn_state:%d, conn_flags:0x%x, status:%d",
799                      p_ccb->con_state, p_ccb->con_flags, res);
800     if (p_ccb->con_state == GAP_CCB_STATE_IDLE) {
801         return;
802     }
803 
804     if (res == BTM_SUCCESS) {
805         p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
806         gap_checks_con_flags (p_ccb);
807     } else {
808         /* security failed - disconnect the channel */
809         L2CA_DISCONNECT_REQ (p_ccb->connection_id);
810     }
811 }
812 
813 /*******************************************************************************
814 **
815 ** Function         gap_connect_cfm
816 **
817 ** Description      This function handles the connect confirm events
818 **                  from L2CAP. This is the case when we are acting as a
819 **                  client and have sent a connect request.
820 **
821 ** Returns          void
822 **
823 *******************************************************************************/
gap_connect_cfm(UINT16 l2cap_cid,UINT16 result)824 static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result)
825 {
826     tGAP_CCB    *p_ccb;
827 
828     /* Find CCB based on CID */
829     if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) {
830         return;
831     }
832 
833     /* initiate security process, if needed */
834     if ( (p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0) {
835         btm_sec_mx_access_request (p_ccb->rem_dev_address, p_ccb->psm, TRUE,
836                                    0, 0, &gap_sec_check_complete, p_ccb);
837     }
838 
839     /* If the connection response contains success status, then */
840     /* Transition to the next state and startup the timer.      */
841     if ((result == L2CAP_CONN_OK) && (p_ccb->con_state == GAP_CCB_STATE_CONN_SETUP)) {
842         p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
843 
844         /* Send a Configuration Request. */
845         L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
846     } else {
847         /* Tell the user if he has a callback */
848         if (p_ccb->p_callback) {
849             (*p_ccb->p_callback) (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
850         }
851 
852         gap_release_ccb (p_ccb);
853     }
854 }
855 
856 /*******************************************************************************
857 **
858 ** Function         gap_config_ind
859 **
860 ** Description      This function processes the L2CAP configuration indication
861 **                  event.
862 **
863 ** Returns          void
864 **
865 *******************************************************************************/
gap_config_ind(UINT16 l2cap_cid,tL2CAP_CFG_INFO * p_cfg)866 static void gap_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
867 {
868     tGAP_CCB    *p_ccb;
869     UINT16      local_mtu_size;
870 
871     /* Find CCB based on CID */
872     if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) {
873         return;
874     }
875 
876     /* Remember the remote MTU size */
877 
878     if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
879         local_mtu_size = p_ccb->ertm_info.user_tx_buf_size
880                          - sizeof(BT_HDR) - L2CAP_MIN_OFFSET;
881     } else {
882         local_mtu_size = L2CAP_MTU_SIZE;
883     }
884 
885     if ((!p_cfg->mtu_present) || (p_cfg->mtu > local_mtu_size)) {
886         p_ccb->rem_mtu_size = local_mtu_size;
887     } else {
888         p_ccb->rem_mtu_size = p_cfg->mtu;
889     }
890 
891     /* For now, always accept configuration from the other side */
892     p_cfg->flush_to_present = FALSE;
893     p_cfg->mtu_present      = FALSE;
894     p_cfg->result           = L2CAP_CFG_OK;
895     p_cfg->fcs_present      = FALSE;
896 
897     L2CA_CONFIG_RSP (l2cap_cid, p_cfg);
898 
899     p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
900 
901     gap_checks_con_flags (p_ccb);
902 }
903 
904 
905 /*******************************************************************************
906 **
907 ** Function         gap_config_cfm
908 **
909 ** Description      This function processes the L2CAP configuration confirmation
910 **                  event.
911 **
912 ** Returns          void
913 **
914 *******************************************************************************/
gap_config_cfm(UINT16 l2cap_cid,tL2CAP_CFG_INFO * p_cfg)915 static void gap_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
916 {
917     tGAP_CCB    *p_ccb;
918 
919     /* Find CCB based on CID */
920     if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) {
921         return;
922     }
923 
924     if (p_cfg->result == L2CAP_CFG_OK) {
925         p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
926 
927 
928         if (p_ccb->cfg.fcr_present) {
929             p_ccb->cfg.fcr.mode = p_cfg->fcr.mode;
930         } else {
931             p_ccb->cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
932         }
933 
934         gap_checks_con_flags (p_ccb);
935     } else {
936         p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
937         gap_release_ccb (p_ccb);
938     }
939 }
940 
941 
942 /*******************************************************************************
943 **
944 ** Function         gap_disconnect_ind
945 **
946 ** Description      This function handles a disconnect event from L2CAP. If
947 **                  requested to, we ack the disconnect before dropping the CCB
948 **
949 ** Returns          void
950 **
951 *******************************************************************************/
gap_disconnect_ind(UINT16 l2cap_cid,BOOLEAN ack_needed)952 static void gap_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed)
953 {
954     tGAP_CCB    *p_ccb;
955 
956     GAP_TRACE_EVENT ("GAP_CONN - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
957 
958     /* Find CCB based on CID */
959     if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) {
960         return;
961     }
962 
963     if (ack_needed) {
964         L2CA_DISCONNECT_RSP (l2cap_cid);
965     }
966 
967     p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
968     gap_release_ccb (p_ccb);
969 }
970 
971 
972 /*******************************************************************************
973 **
974 ** Function         gap_data_ind
975 **
976 ** Description      This function is called when data is received from L2CAP.
977 **
978 ** Returns          void
979 **
980 *******************************************************************************/
gap_data_ind(UINT16 l2cap_cid,BT_HDR * p_msg)981 static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg)
982 {
983     tGAP_CCB    *p_ccb;
984 
985     /* Find CCB based on CID */
986     if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) {
987         osi_free (p_msg);
988         return;
989     }
990 
991     if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
992         fixed_queue_enqueue(p_ccb->rx_queue, p_msg, FIXED_QUEUE_MAX_TIMEOUT);
993 
994         p_ccb->rx_queue_size += p_msg->len;
995         /*
996         GAP_TRACE_EVENT ("gap_data_ind - rx_queue_size=%d, msg len=%d",
997                                        p_ccb->rx_queue_size, p_msg->len);
998          */
999 
1000         p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL);
1001     } else {
1002         osi_free (p_msg);
1003     }
1004 }
1005 
1006 
1007 /*******************************************************************************
1008 **
1009 ** Function         gap_congestion_ind
1010 **
1011 ** Description      This is a callback function called by L2CAP when
1012 **                  data L2CAP congestion status changes
1013 **
1014 *******************************************************************************/
gap_congestion_ind(UINT16 lcid,BOOLEAN is_congested)1015 static void gap_congestion_ind (UINT16 lcid, BOOLEAN is_congested)
1016 {
1017     tGAP_CCB    *p_ccb;
1018     UINT16       event;
1019     BT_HDR      *p_buf;
1020     UINT8        status;
1021 
1022     GAP_TRACE_EVENT ("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x",
1023                      is_congested, lcid);
1024 
1025     /* Find CCB based on CID */
1026     if ((p_ccb = gap_find_ccb_by_cid (lcid)) == NULL) {
1027         return;
1028     }
1029 
1030     p_ccb->is_congested = is_congested;
1031 
1032     event = (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED;
1033     p_ccb->p_callback (p_ccb->gap_handle, event);
1034 
1035     if (!is_congested) {
1036         while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->tx_queue, 0)) != NULL) {
1037             status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
1038 
1039             if (status == L2CAP_DW_CONGESTED) {
1040                 p_ccb->is_congested = TRUE;
1041                 break;
1042             } else if (status != L2CAP_DW_SUCCESS) {
1043                 break;
1044             }
1045         }
1046     }
1047 }
1048 
1049 
1050 /*******************************************************************************
1051 **
1052 ** Function         gap_find_ccb_by_cid
1053 **
1054 ** Description      This function searches the CCB table for an entry with the
1055 **                  passed CID.
1056 **
1057 ** Returns          the CCB address, or NULL if not found.
1058 **
1059 *******************************************************************************/
gap_find_ccb_by_cid(UINT16 cid)1060 static tGAP_CCB *gap_find_ccb_by_cid (UINT16 cid)
1061 {
1062     UINT16       xx;
1063     tGAP_CCB     *p_ccb;
1064 
1065     /* Look through each connection control block */
1066     for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
1067         if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->connection_id == cid)) {
1068             return (p_ccb);
1069         }
1070     }
1071 
1072     /* If here, not found */
1073     return (NULL);
1074 }
1075 
1076 
1077 /*******************************************************************************
1078 **
1079 ** Function         gap_find_ccb_by_handle
1080 **
1081 ** Description      This function searches the CCB table for an entry with the
1082 **                  passed handle.
1083 **
1084 ** Returns          the CCB address, or NULL if not found.
1085 **
1086 *******************************************************************************/
gap_find_ccb_by_handle(UINT16 handle)1087 static tGAP_CCB *gap_find_ccb_by_handle (UINT16 handle)
1088 {
1089     tGAP_CCB     *p_ccb;
1090 
1091     /* Check that handle is valid */
1092     if (handle < GAP_MAX_CONNECTIONS) {
1093         p_ccb = &gap_cb.conn.ccb_pool[handle];
1094 
1095         if (p_ccb->con_state != GAP_CCB_STATE_IDLE) {
1096             return (p_ccb);
1097         }
1098     }
1099 
1100     /* If here, handle points to invalid connection */
1101     return (NULL);
1102 }
1103 
1104 
1105 /*******************************************************************************
1106 **
1107 ** Function         gap_allocate_ccb
1108 **
1109 ** Description      This function allocates a new CCB.
1110 **
1111 ** Returns          CCB address, or NULL if none available.
1112 **
1113 *******************************************************************************/
gap_allocate_ccb(void)1114 static tGAP_CCB *gap_allocate_ccb (void)
1115 {
1116     UINT16       xx;
1117     tGAP_CCB     *p_ccb;
1118 
1119     /* Look through each connection control block for a free one */
1120     for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
1121         if (p_ccb->con_state == GAP_CCB_STATE_IDLE) {
1122             memset (p_ccb, 0, sizeof (tGAP_CCB));
1123             p_ccb->tx_queue = fixed_queue_new(QUEUE_SIZE_MAX);
1124             p_ccb->rx_queue = fixed_queue_new(QUEUE_SIZE_MAX);
1125 
1126             p_ccb->gap_handle   = xx;
1127             p_ccb->rem_mtu_size = L2CAP_MTU_SIZE;
1128 
1129             return (p_ccb);
1130         }
1131     }
1132 
1133     /* If here, no free CCB found */
1134     return (NULL);
1135 }
1136 
1137 
1138 /*******************************************************************************
1139 **
1140 ** Function         gap_release_ccb
1141 **
1142 ** Description      This function releases a CCB.
1143 **
1144 ** Returns          void
1145 **
1146 *******************************************************************************/
gap_release_ccb(tGAP_CCB * p_ccb)1147 static void gap_release_ccb (tGAP_CCB *p_ccb)
1148 {
1149     UINT16       xx;
1150     UINT16      psm = p_ccb->psm;
1151     UINT8       service_id = p_ccb->service_id;
1152 
1153     /* Drop any buffers we may be holding */
1154     p_ccb->rx_queue_size = 0;
1155 
1156     while (!fixed_queue_is_empty(p_ccb->rx_queue)) {
1157         osi_free(fixed_queue_dequeue(p_ccb->rx_queue, 0));
1158 	}
1159     fixed_queue_free(p_ccb->rx_queue, NULL);
1160     p_ccb->rx_queue = NULL;
1161 
1162     while (!fixed_queue_is_empty(p_ccb->tx_queue)) {
1163         osi_free(fixed_queue_dequeue(p_ccb->tx_queue, 0));
1164 	}
1165     fixed_queue_free(p_ccb->tx_queue, NULL);
1166     p_ccb->tx_queue = NULL;
1167 
1168     p_ccb->con_state = GAP_CCB_STATE_IDLE;
1169 
1170     /* If no-one else is using the PSM, deregister from L2CAP */
1171     for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
1172         if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->psm == psm)) {
1173             return;
1174         }
1175     }
1176 #if (SDP_INCLUDED == TRUE)
1177     /* Free the security record for this PSM */
1178     BTM_SecClrService(service_id);
1179 #endif  ///SDP_INCLUDED == TRUE
1180     L2CA_DEREGISTER (psm);
1181 }
1182 
1183 #if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
1184 
1185 /*******************************************************************************
1186 **
1187 ** Function     gap_send_event
1188 **
1189 ** Description  Send BT_EVT_TO_GAP_MSG event to BTU task
1190 **
1191 ** Returns      None
1192 **
1193 *******************************************************************************/
gap_send_event(UINT16 gap_handle)1194 void gap_send_event (UINT16 gap_handle)
1195 {
1196     BT_HDR  *p_msg;
1197 
1198     if ((p_msg = (BT_HDR *)osi_malloc(BT_HDR_SIZE)) != NULL) {
1199         p_msg->event  = BT_EVT_TO_GAP_MSG;
1200         p_msg->len    = 0;
1201         p_msg->offset = 0;
1202         p_msg->layer_specific = gap_handle;
1203 
1204         GKI_send_msg(BTU_TASK, BTU_HCI_RCV_MBOX, p_msg);
1205     } else {
1206         GAP_TRACE_ERROR("Unable to allocate message buffer for event.");
1207     }
1208 }
1209 
1210 #endif /* (GAP_CONN_POST_EVT_INCLUDED == TRUE) */
1211 #endif  /* GAP_CONN_INCLUDED */
1212