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