1 /******************************************************************************
2 *
3 * Copyright 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 #include <base/strings/stringprintf.h>
20 #include <string.h>
21 #include "bt_target.h"
22 #include "device/include/controller.h"
23 #include "gap_api.h"
24 #include "l2c_api.h"
25 #include "l2cdefs.h"
26 #include "osi/include/fixed_queue.h"
27 #include "osi/include/mutex.h"
28 #include "stack/btm/btm_sec.h"
29
30 using base::StringPrintf;
31
32 /* Define the GAP Connection Control Block */
33 typedef struct {
34 #define GAP_CCB_STATE_IDLE 0
35 #define GAP_CCB_STATE_LISTENING 1
36 #define GAP_CCB_STATE_CONN_SETUP 2
37 #define GAP_CCB_STATE_CFG_SETUP 3
38 #define GAP_CCB_STATE_CONNECTED 5
39 uint8_t con_state;
40
41 #define GAP_CCB_FLAGS_IS_ORIG 0x01
42 #define GAP_CCB_FLAGS_HIS_CFG_DONE 0x02
43 #define GAP_CCB_FLAGS_MY_CFG_DONE 0x04
44 #define GAP_CCB_FLAGS_SEC_DONE 0x08
45 #define GAP_CCB_FLAGS_CONN_DONE 0x0E
46 uint8_t con_flags;
47
48 uint8_t service_id; /* Used by BTM */
49 uint16_t gap_handle; /* GAP handle */
50 uint16_t connection_id; /* L2CAP CID */
51 bool rem_addr_specified;
52 uint8_t chan_mode_mask; /* Supported channel modes (FCR) */
53 RawAddress rem_dev_address;
54 uint16_t psm;
55 uint16_t rem_mtu_size;
56
57 bool is_congested;
58 fixed_queue_t* tx_queue; /* Queue of buffers waiting to be sent */
59 fixed_queue_t* rx_queue; /* Queue of buffers waiting to be read */
60
61 uint32_t rx_queue_size; /* Total data count in rx_queue */
62
63 tGAP_CONN_CALLBACK* p_callback; /* Users callback function */
64
65 tL2CAP_CFG_INFO cfg; /* Configuration */
66 tL2CAP_ERTM_INFO ertm_info; /* Pools and modes for ertm */
67 tBT_TRANSPORT transport; /* Transport channel BR/EDR or BLE */
68 tL2CAP_LE_CFG_INFO local_coc_cfg; /* local configuration for LE Coc */
69 tL2CAP_LE_CFG_INFO peer_coc_cfg; /* local configuration for LE Coc */
70 } tGAP_CCB;
71
72 typedef struct {
73 tL2CAP_APPL_INFO reg_info; /* L2CAP Registration info */
74 tGAP_CCB ccb_pool[GAP_MAX_CONNECTIONS];
75 } tGAP_CONN;
76
77 namespace {
78 tGAP_CONN conn;
79 } // namespace
80
81 /******************************************************************************/
82 /* L O C A L F U N C T I O N P R O T O T Y P E S */
83 /******************************************************************************/
84 static void gap_connect_ind(const RawAddress& bd_addr, uint16_t l2cap_cid,
85 uint16_t psm, uint8_t l2cap_id);
86 static void gap_connect_cfm(uint16_t l2cap_cid, uint16_t result);
87 static void gap_config_ind(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg);
88 static void gap_config_cfm(uint16_t l2cap_cid, uint16_t result,
89 tL2CAP_CFG_INFO* p_cfg);
90 static void gap_disconnect_ind(uint16_t l2cap_cid, bool ack_needed);
91 static void gap_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg);
92 static void gap_congestion_ind(uint16_t lcid, bool is_congested);
93 static void gap_tx_complete_ind(uint16_t l2cap_cid, uint16_t sdu_sent);
94 static void gap_on_l2cap_error(uint16_t l2cap_cid, uint16_t result);
95 static tGAP_CCB* gap_find_ccb_by_cid(uint16_t cid);
96 static tGAP_CCB* gap_find_ccb_by_handle(uint16_t handle);
97 static tGAP_CCB* gap_allocate_ccb(void);
98 static void gap_release_ccb(tGAP_CCB* p_ccb);
99 static void gap_checks_con_flags(tGAP_CCB* p_ccb);
100
101 /*******************************************************************************
102 *
103 * Function gap_conn_init
104 *
105 * Description This function is called to initialize GAP connection
106 * management
107 *
108 * Returns void
109 *
110 ******************************************************************************/
gap_conn_init(void)111 void gap_conn_init(void) {
112 memset(&conn, 0, sizeof(tGAP_CONN));
113 conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
114 conn.reg_info.pL2CA_ConnectCfm_Cb = gap_connect_cfm;
115 conn.reg_info.pL2CA_ConfigInd_Cb = gap_config_ind;
116 conn.reg_info.pL2CA_ConfigCfm_Cb = gap_config_cfm;
117 conn.reg_info.pL2CA_DisconnectInd_Cb = gap_disconnect_ind;
118 conn.reg_info.pL2CA_DataInd_Cb = gap_data_ind;
119 conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind;
120 conn.reg_info.pL2CA_TxComplete_Cb = gap_tx_complete_ind;
121 conn.reg_info.pL2CA_Error_Cb = gap_on_l2cap_error;
122 }
123
124 /*******************************************************************************
125 *
126 * Function GAP_ConnOpen
127 *
128 * Description This function is called to open an L2CAP connection.
129 *
130 * Parameters: is_server - If true, the connection is not created
131 * but put into a "listen" mode waiting for
132 * the remote side to connect.
133 *
134 * service_id - Unique service ID from
135 * BTM_SEC_SERVICE_FIRST_EMPTY (6)
136 * to BTM_SEC_MAX_SERVICE_RECORDS (32)
137 *
138 * p_rem_bda - Pointer to remote BD Address.
139 * If a server, and we don't care about the
140 * remote BD Address, then NULL should be passed.
141 *
142 * psm - the PSM used for the connection
143 * le_mps - Maximum PDU Size for LE CoC
144 *
145 * p_config - Optional pointer to configuration structure.
146 * If NULL, the default GAP configuration will
147 * be used.
148 *
149 * security - security flags
150 * chan_mode_mask - (GAP_FCR_CHAN_OPT_BASIC,
151 * GAP_FCR_CHAN_OPT_ERTM,
152 * GAP_FCR_CHAN_OPT_STREAM)
153 *
154 * p_cb - Pointer to callback function for events.
155 *
156 * Returns handle of the connection if successful, else
157 * GAP_INVALID_HANDLE
158 *
159 ******************************************************************************/
GAP_ConnOpen(const char * p_serv_name,uint8_t service_id,bool is_server,const RawAddress * p_rem_bda,uint16_t psm,uint16_t le_mps,tL2CAP_CFG_INFO * p_cfg,tL2CAP_ERTM_INFO * ertm_info,uint16_t security,tGAP_CONN_CALLBACK * p_cb,tBT_TRANSPORT transport)160 uint16_t GAP_ConnOpen(const char* p_serv_name, uint8_t service_id,
161 bool is_server, const RawAddress* p_rem_bda, uint16_t psm,
162 uint16_t le_mps, tL2CAP_CFG_INFO* p_cfg,
163 tL2CAP_ERTM_INFO* ertm_info, uint16_t security,
164 tGAP_CONN_CALLBACK* p_cb, tBT_TRANSPORT transport) {
165 tGAP_CCB* p_ccb;
166 uint16_t cid;
167
168 DVLOG(1) << "GAP_CONN - Open Request";
169
170 /* Allocate a new CCB. Return if none available. */
171 p_ccb = gap_allocate_ccb();
172 if (p_ccb == NULL) return (GAP_INVALID_HANDLE);
173
174 /* update the transport */
175 p_ccb->transport = transport;
176
177 /* The service_id must be set before calling gap_release_ccb(). */
178 p_ccb->service_id = service_id;
179
180 /* If caller specified a BD address, save it */
181 if (p_rem_bda) {
182 /* the bd addr is not RawAddress::kAny, then a bd address was specified */
183 if (*p_rem_bda != RawAddress::kAny) p_ccb->rem_addr_specified = true;
184
185 p_ccb->rem_dev_address = *p_rem_bda;
186 } else if (!is_server) {
187 /* remore addr is not specified and is not a server -> bad */
188 gap_release_ccb(p_ccb);
189 return (GAP_INVALID_HANDLE);
190 }
191
192 /* A client MUST have specified a bd addr to connect with */
193 if (!p_ccb->rem_addr_specified && !is_server) {
194 gap_release_ccb(p_ccb);
195 LOG(ERROR)
196 << "GAP ERROR: Client must specify a remote BD ADDR to connect to!";
197 return (GAP_INVALID_HANDLE);
198 }
199
200 /* Check if configuration was specified */
201 if (p_cfg) p_ccb->cfg = *p_cfg;
202
203 /* Configure L2CAP COC, if transport is LE */
204 if (transport == BT_TRANSPORT_LE) {
205 p_ccb->local_coc_cfg.credits = L2CAP_LE_CREDIT_DEFAULT;
206 p_ccb->local_coc_cfg.mtu = p_cfg->mtu;
207
208 uint16_t max_mps = controller_get_interface()->get_acl_data_size_ble();
209 if (le_mps > max_mps) {
210 LOG(INFO) << "Limiting MPS to one buffer size - " << max_mps;
211 le_mps = max_mps;
212 }
213 p_ccb->local_coc_cfg.mps = le_mps;
214
215 VLOG(2) << __func__ << ": credits=" << p_ccb->local_coc_cfg.credits
216 << ", mps=" << p_ccb->local_coc_cfg.mps
217 << ", mtu=" << p_ccb->local_coc_cfg.mtu;
218 }
219
220 p_ccb->p_callback = p_cb;
221
222 /* If originator, use a dynamic PSM */
223 if (!is_server)
224 conn.reg_info.pL2CA_ConnectInd_Cb = NULL;
225 else
226 conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
227
228 /* Fill in eL2CAP parameter data */
229 if (p_ccb->cfg.fcr_present) {
230 if (ertm_info == NULL) {
231 p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode;
232 } else {
233 p_ccb->ertm_info = *ertm_info;
234 }
235 }
236
237 /* Register the PSM with L2CAP */
238 if (transport == BT_TRANSPORT_BR_EDR) {
239 p_ccb->psm =
240 L2CA_Register2(psm, conn.reg_info, false /* enable_snoop */,
241 &p_ccb->ertm_info, L2CAP_SDU_LENGTH_MAX, 0, security);
242 if (p_ccb->psm == 0) {
243 LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__,
244 psm);
245 gap_release_ccb(p_ccb);
246 return (GAP_INVALID_HANDLE);
247 }
248 }
249
250 if (transport == BT_TRANSPORT_LE) {
251 p_ccb->psm =
252 L2CA_RegisterLECoc(psm, conn.reg_info, security, p_ccb->local_coc_cfg);
253 if (p_ccb->psm == 0) {
254 LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__,
255 psm);
256 gap_release_ccb(p_ccb);
257 return (GAP_INVALID_HANDLE);
258 }
259 }
260
261 if (is_server) {
262 p_ccb->con_flags |=
263 GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */
264 p_ccb->con_state = GAP_CCB_STATE_LISTENING;
265 return (p_ccb->gap_handle);
266 } else {
267 /* We are the originator of this connection */
268 p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG;
269
270 /* Transition to the next appropriate state, waiting for connection confirm.
271 */
272 p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP;
273
274 /* mark security done flag, when security is not required */
275 if ((security & (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) == 0)
276 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
277
278 /* Check if L2CAP started the connection process */
279 if (p_rem_bda && (transport == BT_TRANSPORT_BR_EDR)) {
280 cid = L2CA_ConnectReq2(p_ccb->psm, *p_rem_bda, security);
281 if (cid != 0) {
282 p_ccb->connection_id = cid;
283 return (p_ccb->gap_handle);
284 }
285 }
286
287 if (p_rem_bda && (transport == BT_TRANSPORT_LE)) {
288 cid = L2CA_ConnectLECocReq(p_ccb->psm, *p_rem_bda, &p_ccb->local_coc_cfg,
289 security);
290 if (cid != 0) {
291 p_ccb->connection_id = cid;
292 return (p_ccb->gap_handle);
293 }
294 }
295
296 gap_release_ccb(p_ccb);
297 return (GAP_INVALID_HANDLE);
298 }
299 }
300
301 /*******************************************************************************
302 *
303 * Function GAP_ConnClose
304 *
305 * Description This function is called to close a connection.
306 *
307 * Parameters: handle - Handle of the connection returned by GAP_ConnOpen
308 *
309 * Returns BT_PASS - closed OK
310 * GAP_ERR_BAD_HANDLE - invalid handle
311 *
312 ******************************************************************************/
GAP_ConnClose(uint16_t gap_handle)313 uint16_t GAP_ConnClose(uint16_t gap_handle) {
314 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
315
316 DVLOG(1) << StringPrintf("GAP_CONN - close handle: 0x%x", gap_handle);
317
318 if (p_ccb) {
319 /* Check if we have a connection ID */
320 if (p_ccb->con_state != GAP_CCB_STATE_LISTENING) {
321 if (p_ccb->transport == BT_TRANSPORT_LE) {
322 L2CA_DisconnectLECocReq(p_ccb->connection_id);
323 } else {
324 L2CA_DisconnectReq(p_ccb->connection_id);
325 }
326 }
327
328 gap_release_ccb(p_ccb);
329
330 return (BT_PASS);
331 }
332
333 return (GAP_ERR_BAD_HANDLE);
334 }
335
336 /*******************************************************************************
337 *
338 * Function GAP_ConnReadData
339 *
340 * Description Normally not GKI aware application will call this function
341 * after receiving GAP_EVT_RXDATA event.
342 *
343 * Parameters: handle - Handle of the connection returned in the Open
344 * p_data - Data area
345 * max_len - Byte count requested
346 * p_len - Byte count received
347 *
348 * Returns BT_PASS - data read
349 * GAP_ERR_BAD_HANDLE - invalid handle
350 * GAP_NO_DATA_AVAIL - no data available
351 *
352 ******************************************************************************/
GAP_ConnReadData(uint16_t gap_handle,uint8_t * p_data,uint16_t max_len,uint16_t * p_len)353 uint16_t GAP_ConnReadData(uint16_t gap_handle, uint8_t* p_data,
354 uint16_t max_len, uint16_t* p_len) {
355 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
356 uint16_t copy_len;
357
358 if (!p_ccb) return (GAP_ERR_BAD_HANDLE);
359
360 *p_len = 0;
361
362 if (fixed_queue_is_empty(p_ccb->rx_queue)) return (GAP_NO_DATA_AVAIL);
363
364 mutex_global_lock();
365
366 while (max_len) {
367 BT_HDR* p_buf =
368 static_cast<BT_HDR*>(fixed_queue_try_peek_first(p_ccb->rx_queue));
369 if (p_buf == NULL) break;
370
371 copy_len = (p_buf->len > max_len) ? max_len : p_buf->len;
372 max_len -= copy_len;
373 *p_len += copy_len;
374 if (p_data) {
375 memcpy(p_data, (uint8_t*)(p_buf + 1) + p_buf->offset, copy_len);
376 p_data += copy_len;
377 }
378
379 if (p_buf->len > copy_len) {
380 p_buf->offset += copy_len;
381 p_buf->len -= copy_len;
382 break;
383 }
384 osi_free(fixed_queue_try_dequeue(p_ccb->rx_queue));
385 }
386
387 p_ccb->rx_queue_size -= *p_len;
388
389 mutex_global_unlock();
390
391 DVLOG(1) << StringPrintf(
392 "GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d",
393 p_ccb->rx_queue_size, *p_len);
394
395 return (BT_PASS);
396 }
397
398 /*******************************************************************************
399 *
400 * Function GAP_GetRxQueueCnt
401 *
402 * Description This function return number of bytes on the rx queue.
403 *
404 * Parameters: handle - Handle returned in the GAP_ConnOpen
405 * p_rx_queue_count - Pointer to return queue count in.
406 *
407 *
408 ******************************************************************************/
GAP_GetRxQueueCnt(uint16_t handle,uint32_t * p_rx_queue_count)409 int GAP_GetRxQueueCnt(uint16_t handle, uint32_t* p_rx_queue_count) {
410 tGAP_CCB* p_ccb;
411 int rc = BT_PASS;
412
413 /* Check that handle is valid */
414 if (handle < GAP_MAX_CONNECTIONS) {
415 p_ccb = &conn.ccb_pool[handle];
416
417 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
418 *p_rx_queue_count = p_ccb->rx_queue_size;
419 } else
420 rc = GAP_INVALID_HANDLE;
421 } else
422 rc = GAP_INVALID_HANDLE;
423
424 DVLOG(1) << StringPrintf("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d",
425 rc, *p_rx_queue_count);
426
427 return (rc);
428 }
429
430 /* Try to write the queued data to l2ca. Return true on success, or if queue is
431 * congested. False if error occured when writing. */
gap_try_write_queued_data(tGAP_CCB * p_ccb)432 static bool gap_try_write_queued_data(tGAP_CCB* p_ccb) {
433 if (p_ccb->is_congested) return true;
434
435 /* Send the buffer through L2CAP */
436 BT_HDR* p_buf;
437 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->tx_queue)) != NULL) {
438 uint8_t status;
439 if (p_ccb->transport == BT_TRANSPORT_LE) {
440 status = L2CA_LECocDataWrite(p_ccb->connection_id, p_buf);
441 } else {
442 status = L2CA_DataWrite(p_ccb->connection_id, p_buf);
443 }
444
445 if (status == L2CAP_DW_CONGESTED) {
446 p_ccb->is_congested = true;
447 return true;
448 } else if (status != L2CAP_DW_SUCCESS)
449 return false;
450 }
451 return true;
452 }
453
454 /*******************************************************************************
455 *
456 * Function GAP_ConnWriteData
457 *
458 * Description Normally not GKI aware application will call this function
459 * to send data to the connection.
460 *
461 * Parameters: handle - Handle of the connection returned in the Open
462 * msg - pointer to single SDU to send. This function
463 * will take ownership of it.
464 *
465 * Returns BT_PASS - data read
466 * GAP_ERR_BAD_HANDLE - invalid handle
467 * GAP_ERR_BAD_STATE - connection not established
468 * GAP_CONGESTION - system is congested
469 *
470 ******************************************************************************/
GAP_ConnWriteData(uint16_t gap_handle,BT_HDR * msg)471 uint16_t GAP_ConnWriteData(uint16_t gap_handle, BT_HDR* msg) {
472 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
473
474 if (!p_ccb) {
475 osi_free(msg);
476 return GAP_ERR_BAD_HANDLE;
477 }
478
479 if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) {
480 osi_free(msg);
481 return GAP_ERR_BAD_STATE;
482 }
483
484 if (msg->len > p_ccb->rem_mtu_size) {
485 osi_free(msg);
486 return GAP_ERR_ILL_PARM;
487 }
488
489 DVLOG(1) << StringPrintf("GAP_WriteData %d bytes", msg->len);
490
491 fixed_queue_enqueue(p_ccb->tx_queue, msg);
492
493 if (!gap_try_write_queued_data(p_ccb)) return GAP_ERR_BAD_STATE;
494
495 return (BT_PASS);
496 }
497
498 /*******************************************************************************
499 *
500 * Function GAP_ConnGetRemoteAddr
501 *
502 * Description This function is called to get the remote BD address
503 * of a connection.
504 *
505 * Parameters: handle - Handle of the connection returned by GAP_ConnOpen
506 *
507 * Returns BT_PASS - closed OK
508 * GAP_ERR_BAD_HANDLE - invalid handle
509 *
510 ******************************************************************************/
GAP_ConnGetRemoteAddr(uint16_t gap_handle)511 const RawAddress* GAP_ConnGetRemoteAddr(uint16_t gap_handle) {
512 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
513
514 DVLOG(1) << __func__ << " gap_handle = " << gap_handle;
515
516 if ((p_ccb) && (p_ccb->con_state > GAP_CCB_STATE_LISTENING)) {
517 DVLOG(1) << __func__ << " BDA: " << p_ccb->rem_dev_address;
518 return &p_ccb->rem_dev_address;
519 } else {
520 DVLOG(1) << __func__ << " return Error ";
521 return nullptr;
522 }
523 }
524
525 /*******************************************************************************
526 *
527 * Function GAP_ConnGetRemMtuSize
528 *
529 * Description Returns the remote device's MTU size
530 *
531 * Parameters: handle - Handle of the connection
532 *
533 * Returns uint16_t - maximum size buffer that can be transmitted to
534 * the peer
535 *
536 ******************************************************************************/
GAP_ConnGetRemMtuSize(uint16_t gap_handle)537 uint16_t GAP_ConnGetRemMtuSize(uint16_t gap_handle) {
538 tGAP_CCB* p_ccb;
539
540 p_ccb = gap_find_ccb_by_handle(gap_handle);
541 if (p_ccb == NULL) return (0);
542
543 return (p_ccb->rem_mtu_size);
544 }
545
546 /*******************************************************************************
547 *
548 * Function GAP_ConnGetL2CAPCid
549 *
550 * Description Returns the L2CAP channel id
551 *
552 * Parameters: handle - Handle of the connection
553 *
554 * Returns uint16_t - The L2CAP channel id
555 * 0, if error
556 *
557 ******************************************************************************/
GAP_ConnGetL2CAPCid(uint16_t gap_handle)558 uint16_t GAP_ConnGetL2CAPCid(uint16_t gap_handle) {
559 tGAP_CCB* p_ccb;
560
561 p_ccb = gap_find_ccb_by_handle(gap_handle);
562 if (p_ccb == NULL) return (0);
563
564 return (p_ccb->connection_id);
565 }
566
567 /*******************************************************************************
568 *
569 * Function gap_tx_connect_ind
570 *
571 * Description Sends out GAP_EVT_TX_EMPTY when transmission has been
572 * completed.
573 *
574 * Returns void
575 *
576 ******************************************************************************/
gap_tx_complete_ind(uint16_t l2cap_cid,uint16_t sdu_sent)577 void gap_tx_complete_ind(uint16_t l2cap_cid, uint16_t sdu_sent) {
578 tGAP_CCB* p_ccb = gap_find_ccb_by_cid(l2cap_cid);
579 if (p_ccb == NULL) return;
580
581 if ((p_ccb->con_state == GAP_CCB_STATE_CONNECTED) && (sdu_sent == 0xFFFF)) {
582 DVLOG(1) << StringPrintf("%s: GAP_EVT_TX_EMPTY", __func__);
583 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_TX_EMPTY, nullptr);
584 }
585 }
586
587 /*******************************************************************************
588 *
589 * Function gap_connect_ind
590 *
591 * Description This function handles an inbound connection indication
592 * from L2CAP. This is the case where we are acting as a
593 * server.
594 *
595 * Returns void
596 *
597 ******************************************************************************/
gap_connect_ind(const RawAddress & bd_addr,uint16_t l2cap_cid,uint16_t psm,uint8_t l2cap_id)598 static void gap_connect_ind(const RawAddress& bd_addr, uint16_t l2cap_cid,
599 uint16_t psm, uint8_t l2cap_id) {
600 uint16_t xx;
601 tGAP_CCB* p_ccb;
602
603 /* See if we have a CCB listening for the connection */
604 for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
605 if ((p_ccb->con_state == GAP_CCB_STATE_LISTENING) && (p_ccb->psm == psm) &&
606 (!p_ccb->rem_addr_specified || (bd_addr == p_ccb->rem_dev_address)))
607 break;
608 }
609
610 if (xx == GAP_MAX_CONNECTIONS) {
611 LOG(WARNING) << "*******";
612 LOG(WARNING) << "WARNING: GAP Conn Indication for Unexpected Bd "
613 "Addr...Disconnecting";
614 LOG(WARNING) << "*******";
615
616 /* Disconnect because it is an unexpected connection */
617 if (p_ccb->transport == BT_TRANSPORT_LE) {
618 L2CA_DisconnectLECocReq(l2cap_cid);
619 } else {
620 L2CA_DisconnectReq(l2cap_cid);
621 }
622 return;
623 }
624
625 /* Transition to the next appropriate state, waiting for config setup. */
626 if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
627 p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
628
629 /* Save the BD Address and Channel ID. */
630 p_ccb->rem_dev_address = bd_addr;
631 p_ccb->connection_id = l2cap_cid;
632
633 if (p_ccb->transport == BT_TRANSPORT_LE) {
634 /* get the remote coc configuration */
635 L2CA_GetPeerLECocConfig(l2cap_cid, &p_ccb->peer_coc_cfg);
636 p_ccb->rem_mtu_size = p_ccb->peer_coc_cfg.mtu;
637
638 /* configuration is not required for LE COC */
639 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
640 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
641 gap_checks_con_flags(p_ccb);
642 }
643
644 DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x",
645 p_ccb->connection_id);
646 }
647
648 /*******************************************************************************
649 *
650 * Function gap_checks_con_flags
651 *
652 * Description This function processes the L2CAP configuration indication
653 * event.
654 *
655 * Returns void
656 *
657 ******************************************************************************/
gap_checks_con_flags(tGAP_CCB * p_ccb)658 static void gap_checks_con_flags(tGAP_CCB* p_ccb) {
659 DVLOG(1) << __func__ << " conn_flags:0x" << +p_ccb->con_flags;
660 /* if all the required con_flags are set, report the OPEN event now */
661 if ((p_ccb->con_flags & GAP_CCB_FLAGS_CONN_DONE) == GAP_CCB_FLAGS_CONN_DONE) {
662 p_ccb->con_state = GAP_CCB_STATE_CONNECTED;
663
664 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_OPENED, nullptr);
665 }
666 }
667
668 /*******************************************************************************
669 *
670 * Function gap_sec_check_complete
671 *
672 * Description The function called when Security Manager finishes
673 * verification of the service side connection
674 *
675 * Returns void
676 *
677 ******************************************************************************/
gap_sec_check_complete(tGAP_CCB * p_ccb)678 static void gap_sec_check_complete(tGAP_CCB* p_ccb) {
679 if (p_ccb->con_state == GAP_CCB_STATE_IDLE) return;
680 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
681 gap_checks_con_flags(p_ccb);
682 }
683
gap_on_l2cap_error(uint16_t l2cap_cid,uint16_t result)684 static void gap_on_l2cap_error(uint16_t l2cap_cid, uint16_t result) {
685 tGAP_CCB* p_ccb = gap_find_ccb_by_cid(l2cap_cid);
686 if (p_ccb == nullptr) return;
687
688 /* Tell the user if there is a callback */
689 if (p_ccb->p_callback)
690 (*p_ccb->p_callback)(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED, nullptr);
691
692 gap_release_ccb(p_ccb);
693 }
694
695 /*******************************************************************************
696 *
697 * Function gap_connect_cfm
698 *
699 * Description This function handles the connect confirm events
700 * from L2CAP. This is the case when we are acting as a
701 * client and have sent a connect request.
702 *
703 * Returns void
704 *
705 ******************************************************************************/
gap_connect_cfm(uint16_t l2cap_cid,uint16_t result)706 static void gap_connect_cfm(uint16_t l2cap_cid, uint16_t result) {
707 tGAP_CCB* p_ccb;
708
709 /* Find CCB based on CID */
710 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
711 if (p_ccb == NULL) return;
712
713 /* initiate security process, if needed */
714 if ((p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0 &&
715 p_ccb->transport != BT_TRANSPORT_LE) {
716 // Assume security check is done by L2cap
717 gap_sec_check_complete(p_ccb);
718 }
719
720 /* If the connection response contains success status, then */
721 /* Transition to the next state and startup the timer. */
722 if ((result == L2CAP_CONN_OK) &&
723 (p_ccb->con_state == GAP_CCB_STATE_CONN_SETUP)) {
724 if (p_ccb->transport == BT_TRANSPORT_BR_EDR) {
725 p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
726 }
727
728 if (p_ccb->transport == BT_TRANSPORT_LE) {
729 /* get the remote coc configuration */
730 L2CA_GetPeerLECocConfig(l2cap_cid, &p_ccb->peer_coc_cfg);
731 p_ccb->rem_mtu_size = p_ccb->peer_coc_cfg.mtu;
732
733 /* configuration is not required for LE COC */
734 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
735 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
736 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
737 gap_checks_con_flags(p_ccb);
738 }
739 }
740 }
741
742 /*******************************************************************************
743 *
744 * Function gap_config_ind
745 *
746 * Description This function processes the L2CAP configuration indication
747 * event.
748 *
749 * Returns void
750 *
751 ******************************************************************************/
gap_config_ind(uint16_t l2cap_cid,tL2CAP_CFG_INFO * p_cfg)752 static void gap_config_ind(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg) {
753 tGAP_CCB* p_ccb;
754 uint16_t local_mtu_size;
755
756 /* Find CCB based on CID */
757 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
758 if (p_ccb == NULL) return;
759
760 /* Remember the remote MTU size */
761
762 if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
763 local_mtu_size = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR) - L2CAP_MIN_OFFSET;
764 } else
765 local_mtu_size = L2CAP_MTU_SIZE;
766
767 if ((!p_cfg->mtu_present) || (p_cfg->mtu > local_mtu_size)) {
768 p_ccb->rem_mtu_size = local_mtu_size;
769 } else
770 p_ccb->rem_mtu_size = p_cfg->mtu;
771 }
772
773 /*******************************************************************************
774 *
775 * Function gap_config_cfm
776 *
777 * Description This function processes the L2CAP configuration confirmation
778 * event.
779 *
780 * Returns void
781 *
782 ******************************************************************************/
gap_config_cfm(uint16_t l2cap_cid,uint16_t initiator,tL2CAP_CFG_INFO * p_cfg)783 static void gap_config_cfm(uint16_t l2cap_cid, uint16_t initiator,
784 tL2CAP_CFG_INFO* p_cfg) {
785 gap_config_ind(l2cap_cid, p_cfg);
786
787 tGAP_CCB* p_ccb;
788
789 /* Find CCB based on CID */
790 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
791 if (p_ccb == NULL) return;
792
793 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
794 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
795 gap_checks_con_flags(p_ccb);
796 }
797
798 /*******************************************************************************
799 *
800 * Function gap_disconnect_ind
801 *
802 * Description This function handles a disconnect event from L2CAP. If
803 * requested to, we ack the disconnect before dropping the CCB
804 *
805 * Returns void
806 *
807 ******************************************************************************/
gap_disconnect_ind(uint16_t l2cap_cid,bool ack_needed)808 static void gap_disconnect_ind(uint16_t l2cap_cid, bool ack_needed) {
809 tGAP_CCB* p_ccb;
810
811 DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
812
813 /* Find CCB based on CID */
814 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
815 if (p_ccb == NULL) return;
816
817 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED, nullptr);
818 gap_release_ccb(p_ccb);
819 }
820
821 /*******************************************************************************
822 *
823 * Function gap_data_ind
824 *
825 * Description This function is called when data is received from L2CAP.
826 *
827 * Returns void
828 *
829 ******************************************************************************/
gap_data_ind(uint16_t l2cap_cid,BT_HDR * p_msg)830 static void gap_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg) {
831 tGAP_CCB* p_ccb;
832
833 /* Find CCB based on CID */
834 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
835 if (p_ccb == NULL) {
836 osi_free(p_msg);
837 return;
838 }
839
840 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
841 fixed_queue_enqueue(p_ccb->rx_queue, p_msg);
842
843 p_ccb->rx_queue_size += p_msg->len;
844 /*
845 DVLOG(1) << StringPrintf ("gap_data_ind - rx_queue_size=%d, msg len=%d",
846 p_ccb->rx_queue_size, p_msg->len);
847 */
848
849 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL, nullptr);
850 } else {
851 osi_free(p_msg);
852 }
853 }
854
855 /*******************************************************************************
856 *
857 * Function gap_congestion_ind
858 *
859 * Description This is a callback function called by L2CAP when
860 * data L2CAP congestion status changes
861 *
862 ******************************************************************************/
gap_congestion_ind(uint16_t lcid,bool is_congested)863 static void gap_congestion_ind(uint16_t lcid, bool is_congested) {
864 DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x",
865 is_congested, lcid);
866
867 tGAP_CCB* p_ccb = gap_find_ccb_by_cid(lcid); /* Find CCB based on CID */
868 if (!p_ccb) return;
869
870 p_ccb->is_congested = is_congested;
871
872 p_ccb->p_callback(
873 p_ccb->gap_handle,
874 (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED,
875 nullptr);
876
877 gap_try_write_queued_data(p_ccb);
878 }
879
880 /*******************************************************************************
881 *
882 * Function gap_find_ccb_by_cid
883 *
884 * Description This function searches the CCB table for an entry with the
885 * passed CID.
886 *
887 * Returns the CCB address, or NULL if not found.
888 *
889 ******************************************************************************/
gap_find_ccb_by_cid(uint16_t cid)890 static tGAP_CCB* gap_find_ccb_by_cid(uint16_t cid) {
891 uint16_t xx;
892 tGAP_CCB* p_ccb;
893
894 /* Look through each connection control block */
895 for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
896 if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) &&
897 (p_ccb->connection_id == cid))
898 return (p_ccb);
899 }
900
901 /* If here, not found */
902 return (NULL);
903 }
904
905 /*******************************************************************************
906 *
907 * Function gap_find_ccb_by_handle
908 *
909 * Description This function searches the CCB table for an entry with the
910 * passed handle.
911 *
912 * Returns the CCB address, or NULL if not found.
913 *
914 ******************************************************************************/
gap_find_ccb_by_handle(uint16_t handle)915 static tGAP_CCB* gap_find_ccb_by_handle(uint16_t handle) {
916 tGAP_CCB* p_ccb;
917
918 /* Check that handle is valid */
919 if (handle < GAP_MAX_CONNECTIONS) {
920 p_ccb = &conn.ccb_pool[handle];
921
922 if (p_ccb->con_state != GAP_CCB_STATE_IDLE) return (p_ccb);
923 }
924
925 /* If here, handle points to invalid connection */
926 return (NULL);
927 }
928
929 /*******************************************************************************
930 *
931 * Function gap_allocate_ccb
932 *
933 * Description This function allocates a new CCB.
934 *
935 * Returns CCB address, or NULL if none available.
936 *
937 ******************************************************************************/
gap_allocate_ccb(void)938 static tGAP_CCB* gap_allocate_ccb(void) {
939 uint16_t xx;
940 tGAP_CCB* p_ccb;
941
942 /* Look through each connection control block for a free one */
943 for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
944 if (p_ccb->con_state == GAP_CCB_STATE_IDLE) {
945 memset(p_ccb, 0, sizeof(tGAP_CCB));
946 p_ccb->tx_queue = fixed_queue_new(SIZE_MAX);
947 p_ccb->rx_queue = fixed_queue_new(SIZE_MAX);
948
949 p_ccb->gap_handle = xx;
950 p_ccb->rem_mtu_size = L2CAP_MTU_SIZE;
951
952 return (p_ccb);
953 }
954 }
955
956 /* If here, no free CCB found */
957 return (NULL);
958 }
959
960 /*******************************************************************************
961 *
962 * Function gap_release_ccb
963 *
964 * Description This function releases a CCB.
965 *
966 * Returns void
967 *
968 ******************************************************************************/
gap_release_ccb(tGAP_CCB * p_ccb)969 static void gap_release_ccb(tGAP_CCB* p_ccb) {
970 /* Drop any buffers we may be holding */
971 p_ccb->rx_queue_size = 0;
972
973 while (!fixed_queue_is_empty(p_ccb->rx_queue))
974 osi_free(fixed_queue_try_dequeue(p_ccb->rx_queue));
975 fixed_queue_free(p_ccb->rx_queue, NULL);
976 p_ccb->rx_queue = NULL;
977
978 while (!fixed_queue_is_empty(p_ccb->tx_queue))
979 osi_free(fixed_queue_try_dequeue(p_ccb->tx_queue));
980 fixed_queue_free(p_ccb->tx_queue, NULL);
981 p_ccb->tx_queue = NULL;
982
983 p_ccb->con_state = GAP_CCB_STATE_IDLE;
984
985 /* If no-one else is using the PSM, deregister from L2CAP */
986 tGAP_CCB* p_ccb_local = conn.ccb_pool;
987 for (uint16_t i = 0; i < GAP_MAX_CONNECTIONS; i++, p_ccb_local++) {
988 if ((p_ccb_local->con_state != GAP_CCB_STATE_IDLE) &&
989 (p_ccb_local->psm == p_ccb->psm)) {
990 DVLOG(1) << __func__ << " : " << +p_ccb_local->psm
991 << " PSM is still in use, do not deregister";
992 return;
993 }
994 }
995
996 /* Free the security record for this PSM */
997 BTM_SecClrServiceByPsm(p_ccb->psm);
998 if (p_ccb->transport == BT_TRANSPORT_BR_EDR) L2CA_Deregister(p_ccb->psm);
999 if (p_ccb->transport == BT_TRANSPORT_LE) L2CA_DeregisterLECoc(p_ccb->psm);
1000 }
1001
1002 extern void gap_attr_db_init(void);
1003
1004 /*
1005 * This routine should not be called except once per stack invocation.
1006 */
GAP_Init(void)1007 void GAP_Init(void) {
1008 gap_conn_init();
1009 gap_attr_db_init();
1010 }
1011