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