1 /******************************************************************************
2 *
3 * Copyright (C) 1999-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This file contains L2CAP utility functions
22 *
23 ******************************************************************************/
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "osi/allocator.h"
29 #include "device/controller.h"
30 #include "stack/bt_types.h"
31 #include "stack/hcimsgs.h"
32 #include "stack/l2cdefs.h"
33 #include "l2c_int.h"
34 #include "stack/hcidefs.h"
35 #include "stack/btu.h"
36 #include "stack/btm_api.h"
37 #include "btm_int.h"
38 #include "stack/hcidefs.h"
39 #include "osi/allocator.h"
40 #include "osi/list.h"
41
42 #if BT_SDP_BQB_INCLUDED
43 extern BOOLEAN l2cap_bqb_ertm_mode_included_flag;
44 #endif /* BT_SDP_BQB_INCLUDED */
45
46 /*******************************************************************************
47 **
48 ** Function l2cu_allocate_lcb
49 **
50 ** Description Look for an unused LCB
51 **
52 ** Returns LCB address or NULL if none found
53 **
54 *******************************************************************************/
l2cu_allocate_lcb(BD_ADDR p_bd_addr,BOOLEAN is_bonding,tBT_TRANSPORT transport)55 tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding, tBT_TRANSPORT transport)
56 {
57 tL2C_LCB *p_lcb = NULL;
58 bool list_ret = false;
59 extern tL2C_LCB *l2cu_find_free_lcb (void);
60 // temp solution
61 p_lcb = l2cu_find_free_lcb();
62 if(p_lcb != NULL) {
63 list_ret = true;
64 }
65
66 #if (CLASSIC_BT_INCLUDED == TRUE)
67 /* Check if peer device's and our BD_ADDR is same or not. It
68 should be different to avoid 'Impersonation in the Pin Pairing
69 Protocol' (CVE-2020-26555) vulnerability. */
70 if (memcmp((uint8_t *)p_bd_addr, (uint8_t *)&controller_get_interface()->get_address()->address, sizeof (BD_ADDR)) == 0) {
71 L2CAP_TRACE_ERROR ("%s connection rejected due to same BD ADDR", __func__);
72 return (NULL);
73 }
74 #endif
75
76 if(p_lcb == NULL && list_length(l2cb.p_lcb_pool) < MAX_L2CAP_LINKS) {
77 p_lcb = (tL2C_LCB *)osi_malloc(sizeof(tL2C_LCB));
78 if (p_lcb) {
79 memset (p_lcb, 0, sizeof(tL2C_LCB));
80 list_ret = list_append(l2cb.p_lcb_pool, p_lcb);
81 }else {
82 L2CAP_TRACE_ERROR("Error in allocating L2CAP Link Control Block");
83 }
84 }
85 if (list_ret) {
86 if (p_lcb) {
87 btu_free_timer(&p_lcb->timer_entry);
88 btu_free_timer(&p_lcb->info_timer_entry);
89 btu_free_timer(&p_lcb->upda_con_timer);
90
91 memset (p_lcb, 0, sizeof (tL2C_LCB));
92 memcpy (p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN);
93
94 p_lcb->in_use = TRUE;
95 p_lcb->link_state = LST_DISCONNECTED;
96 p_lcb->handle = HCI_INVALID_HANDLE;
97 p_lcb->link_flush_tout = 0xFFFF;
98 p_lcb->timer_entry.param = (TIMER_PARAM_TYPE)p_lcb;
99 p_lcb->info_timer_entry.param = (TIMER_PARAM_TYPE)p_lcb;
100 p_lcb->upda_con_timer.param = (TIMER_PARAM_TYPE)p_lcb;
101 p_lcb->idle_timeout = l2cb.idle_timeout;
102 p_lcb->id = 1; /* spec does not allow '0' */
103 p_lcb->is_bonding = is_bonding;
104 #if (BLE_INCLUDED == TRUE)
105 p_lcb->transport = transport;
106 p_lcb->tx_data_len = controller_get_interface()->get_ble_default_data_packet_length();
107 p_lcb->le_sec_pending_q = fixed_queue_new(QUEUE_SIZE_MAX);
108
109 if (transport == BT_TRANSPORT_LE) {
110 l2cb.num_ble_links_active++;
111 l2c_ble_link_adjust_allocation();
112 } else
113 #endif
114 {
115 l2cb.num_links_active++;
116 l2c_link_adjust_allocation();
117 }
118 p_lcb->link_xmit_data_q = list_new(NULL);
119 return (p_lcb);
120 }
121 }
122
123 /* If here, no free LCB found */
124 return (NULL);
125 }
126
127 /*******************************************************************************
128 **
129 ** Function l2cu_update_lcb_4_bonding
130 **
131 ** Description Mark the lcb for bonding. Used when bonding takes place on
132 ** an existing ACL connection. (Pre-Lisbon devices)
133 **
134 ** Returns Nothing
135 **
136 *******************************************************************************/
l2cu_update_lcb_4_bonding(BD_ADDR p_bd_addr,BOOLEAN is_bonding)137 void l2cu_update_lcb_4_bonding (BD_ADDR p_bd_addr, BOOLEAN is_bonding)
138 {
139 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (p_bd_addr, BT_TRANSPORT_BR_EDR);
140
141 if (p_lcb) {
142 p_lcb->is_bonding = is_bonding;
143 }
144 }
145
146 /*******************************************************************************
147 **
148 ** Function l2cu_release_lcb
149 **
150 ** Description Release an LCB. All timers will be stopped, channels
151 ** dropped, buffers returned etc.
152 **
153 ** Returns void
154 **
155 *******************************************************************************/
l2cu_release_lcb(tL2C_LCB * p_lcb)156 void l2cu_release_lcb (tL2C_LCB *p_lcb)
157 {
158 tL2C_CCB *p_ccb;
159
160 p_lcb->in_use = FALSE;
161 p_lcb->is_bonding = FALSE;
162 #if (BLE_INCLUDED == TRUE)
163 p_lcb->retry_create_con = 0;
164 p_lcb->start_time_s = 0;
165 #endif // #if (BLE_INCLUDED == TRUE)
166
167 /* Stop and release timers */
168 btu_free_timer (&p_lcb->timer_entry);
169 memset(&p_lcb->timer_entry, 0, sizeof(TIMER_LIST_ENT));
170 btu_free_timer (&p_lcb->info_timer_entry);
171 memset(&p_lcb->info_timer_entry, 0, sizeof(TIMER_LIST_ENT));
172 btu_free_timer(&p_lcb->upda_con_timer);
173 memset(&p_lcb->upda_con_timer, 0, sizeof(TIMER_LIST_ENT));
174
175 /* Release any unfinished L2CAP packet on this link */
176 if (p_lcb->p_hcit_rcv_acl) {
177 osi_free(p_lcb->p_hcit_rcv_acl);
178 p_lcb->p_hcit_rcv_acl = NULL;
179 }
180
181 #if BTM_SCO_INCLUDED == TRUE
182 #if (BLE_INCLUDED == TRUE)
183 if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
184 #endif
185 {
186 /* Release all SCO links */
187 btm_remove_sco_links(p_lcb->remote_bd_addr);
188 }
189 #endif
190
191 if (p_lcb->sent_not_acked > 0) {
192 #if (BLE_INCLUDED == TRUE)
193 if (p_lcb->transport == BT_TRANSPORT_LE) {
194 l2cb.controller_le_xmit_window += p_lcb->sent_not_acked;
195 if (l2cb.controller_le_xmit_window > l2cb.num_lm_ble_bufs) {
196 l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
197 }
198 } else
199 #endif
200 {
201 l2cb.controller_xmit_window += p_lcb->sent_not_acked;
202 if (l2cb.controller_xmit_window > l2cb.num_lm_acl_bufs) {
203 l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
204 }
205 }
206 }
207
208 #if (BLE_INCLUDED == TRUE)
209 // Reset BLE connecting flag only if the address matches
210 if (!memcmp(l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN)) {
211 l2cb.is_ble_connecting = FALSE;
212 }
213 #endif
214
215 #if (L2CAP_NUM_FIXED_CHNLS > 0)
216 l2cu_process_fixed_disc_cback(p_lcb);
217 #endif
218
219 /* Ensure no CCBs left on this LCB */
220 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_lcb->ccb_queue.p_first_ccb) {
221 l2cu_release_ccb (p_ccb);
222 }
223
224 /* Tell BTM Acl management the link was removed */
225 if ((p_lcb->link_state == LST_CONNECTED) || (p_lcb->link_state == LST_DISCONNECTING)) {
226 #if (BLE_INCLUDED == TRUE)
227 btm_acl_removed (p_lcb->remote_bd_addr, p_lcb->transport);
228 #else
229 btm_acl_removed (p_lcb->remote_bd_addr, BT_TRANSPORT_BR_EDR);
230 #endif
231 }
232
233 /* Release any held buffers */
234 if (p_lcb->link_xmit_data_q) {
235 while (!list_is_empty(p_lcb->link_xmit_data_q)) {
236 BT_HDR *p_buf = list_front(p_lcb->link_xmit_data_q);
237 list_remove(p_lcb->link_xmit_data_q, p_buf);
238 osi_free(p_buf);
239 }
240 list_free(p_lcb->link_xmit_data_q);
241 p_lcb->link_xmit_data_q = NULL;
242 }
243
244 #if (L2CAP_UCD_INCLUDED == TRUE)
245 /* clean up any security pending UCD */
246 l2c_ucd_delete_sec_pending_q(p_lcb);
247 #endif
248
249 #if BLE_INCLUDED == TRUE
250 /* Re-adjust flow control windows make sure it does not go negative */
251 if (p_lcb->transport == BT_TRANSPORT_LE) {
252 if (l2cb.num_ble_links_active >= 1) {
253 l2cb.num_ble_links_active--;
254 }
255
256 l2c_ble_link_adjust_allocation();
257 } else
258 #endif
259 {
260 if (l2cb.num_links_active >= 1) {
261 l2cb.num_links_active--;
262 }
263
264 l2c_link_adjust_allocation();
265 }
266
267 /* Check for ping outstanding */
268 if (p_lcb->p_echo_rsp_cb) {
269 tL2CA_ECHO_RSP_CB *p_cb = p_lcb->p_echo_rsp_cb;
270
271 /* Zero out the callback in case app immediately calls us again */
272 p_lcb->p_echo_rsp_cb = NULL;
273
274 (*p_cb) (L2CAP_PING_RESULT_NO_LINK);
275 }
276
277 #if (BLE_INCLUDED == TRUE)
278 /* Check and release all the LE COC connections waiting for security */
279 if (p_lcb->le_sec_pending_q)
280 {
281 while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
282 {
283 tL2CAP_SEC_DATA *p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q, FIXED_QUEUE_MAX_TIMEOUT);
284 if (p_buf->p_callback) {
285 p_buf->p_callback(p_lcb->remote_bd_addr, p_lcb->transport, p_buf->p_ref_data, BTM_DEV_RESET);
286 }
287 osi_free(p_buf);
288 }
289 fixed_queue_free(p_lcb->le_sec_pending_q, NULL);
290 p_lcb->le_sec_pending_q = NULL;
291 }
292 #endif ///BLE_INCLUDED == TRUE
293 }
294
295
296 /*******************************************************************************
297 **
298 ** Function l2cu_find_lcb_by_bd_addr
299 **
300 ** Description Look through all active LCBs for a match based on the
301 ** remote BD address.
302 **
303 ** Returns pointer to matched LCB, or NULL if no match
304 **
305 *******************************************************************************/
l2cu_find_lcb_by_bd_addr(BD_ADDR p_bd_addr,tBT_TRANSPORT transport)306 tL2C_LCB *l2cu_find_lcb_by_bd_addr (BD_ADDR p_bd_addr, tBT_TRANSPORT transport)
307 {
308 list_node_t *p_node = NULL;
309 tL2C_LCB *p_lcb = NULL;
310 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
311 p_lcb = list_node(p_node);
312 if ((p_lcb->in_use) &&
313 #if BLE_INCLUDED == TRUE
314 p_lcb->transport == transport &&
315 #endif
316 (!memcmp (p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN))) {
317 return (p_lcb);
318 }
319 }
320
321 /* If here, no match found */
322 return (NULL);
323 }
324
l2cu_find_free_lcb(void)325 tL2C_LCB *l2cu_find_free_lcb (void)
326 {
327 list_node_t *p_node = NULL;
328 tL2C_LCB *p_lcb = NULL;
329 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
330 p_lcb = list_node(p_node);
331 if (!p_lcb->in_use) {
332 return (p_lcb);
333 }
334 }
335 /* If here, no match found */
336 return (NULL);
337 }
338
l2cu_plcb_active_count(void)339 uint8_t l2cu_plcb_active_count(void)
340 {
341 list_node_t *p_node = NULL;
342 tL2C_LCB *p_lcb = NULL;
343 uint8_t active_count = 0;
344 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
345 p_lcb = list_node(p_node);
346 if (p_lcb && p_lcb->in_use) {
347 active_count ++;
348 }
349 }
350 if (active_count >= MAX_L2CAP_CHANNELS) {
351 L2CAP_TRACE_ERROR("error active count");
352 active_count = 0;
353 }
354 L2CAP_TRACE_DEBUG("plcb active count %d", active_count);
355 return active_count;
356
357 }
358
359 /*******************************************************************************
360 **
361 ** Function l2cu_get_conn_role
362 **
363 ** Description Determine the desired role (master or slave) of a link.
364 ** If already got a slave link, this one must be a master. If
365 ** already got at least 1 link where we are the master, make this
366 ** also a master.
367 **
368 ** Returns HCI_ROLE_MASTER or HCI_ROLE_SLAVE
369 **
370 *******************************************************************************/
l2cu_get_conn_role(tL2C_LCB * p_this_lcb)371 UINT8 l2cu_get_conn_role (tL2C_LCB *p_this_lcb)
372 {
373 return l2cb.desire_role;
374 }
375
376 /*******************************************************************************
377 **
378 ** Function l2c_is_cmd_rejected
379 **
380 ** Description Checks if cmd_code is command or response
381 ** If a command it will be rejected per spec.
382 ** This function is used when a illegal packet length is detected
383 **
384 ** Returns BOOLEAN - TRUE if cmd_code is a command and it is rejected,
385 ** FALSE if response code. (command not rejected)
386 **
387 *******************************************************************************/
l2c_is_cmd_rejected(UINT8 cmd_code,UINT8 id,tL2C_LCB * p_lcb)388 BOOLEAN l2c_is_cmd_rejected (UINT8 cmd_code, UINT8 id, tL2C_LCB *p_lcb)
389 {
390 switch (cmd_code) {
391 case L2CAP_CMD_CONN_REQ:
392 case L2CAP_CMD_CONFIG_REQ:
393 case L2CAP_CMD_DISC_REQ:
394 case L2CAP_CMD_ECHO_REQ:
395 case L2CAP_CMD_INFO_REQ:
396 case L2CAP_CMD_AMP_CONN_REQ:
397 case L2CAP_CMD_AMP_MOVE_REQ:
398 case L2CAP_CMD_BLE_UPDATE_REQ:
399 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_MTU_EXCEEDED, id, L2CAP_DEFAULT_MTU, 0);
400 L2CAP_TRACE_WARNING ("Dumping first Command (%d)", cmd_code);
401 return TRUE;
402
403 default: /* Otherwise a response */
404 return FALSE;
405 }
406 }
407
408 /*******************************************************************************
409 **
410 ** Function l2cu_build_header
411 **
412 ** Description Builds the L2CAP command packet header
413 **
414 ** Returns Pointer to allocated packet or NULL if no resources
415 **
416 *******************************************************************************/
l2cu_build_header(tL2C_LCB * p_lcb,UINT16 len,UINT8 cmd,UINT8 id)417 BT_HDR *l2cu_build_header (tL2C_LCB *p_lcb, UINT16 len, UINT8 cmd, UINT8 id)
418 {
419 BT_HDR *p_buf = (BT_HDR *)osi_malloc(L2CAP_CMD_BUF_SIZE);
420 UINT8 *p;
421
422 if (!p_buf) {
423 return (NULL);
424 }
425
426 p_buf->offset = L2CAP_SEND_CMD_OFFSET;
427 p_buf->len = len + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
428 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
429
430 /* Put in HCI header - handle + pkt boundary */
431 #if (BLE_INCLUDED == TRUE)
432 if (p_lcb->transport == BT_TRANSPORT_LE) {
433 UINT16_TO_STREAM (p, (p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT)));
434 } else
435 #endif
436 {
437 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
438 UINT16_TO_STREAM (p, p_lcb->handle | l2cb.non_flushable_pbf);
439 #else
440 UINT16_TO_STREAM (p, (p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
441 #endif
442 }
443
444 UINT16_TO_STREAM (p, len + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD);
445 UINT16_TO_STREAM (p, len + L2CAP_CMD_OVERHEAD);
446
447 #if (BLE_INCLUDED == TRUE)
448 if (p_lcb->transport == BT_TRANSPORT_LE) {
449 //counter_add("l2cap.ble.tx.bytes", p_buf->len);
450 //counter_add("l2cap.ble.tx.pkts", 1);
451
452 UINT16_TO_STREAM (p, L2CAP_BLE_SIGNALLING_CID);
453 } else
454 #endif
455 {
456 //counter_add("l2cap.sig.tx.bytes", p_buf->len);
457 //counter_add("l2cap.sig.tx.pkts", 1);
458 UINT16_TO_STREAM (p, L2CAP_SIGNALLING_CID);
459 }
460
461 /* Put in L2CAP command header */
462 UINT8_TO_STREAM (p, cmd);
463 UINT8_TO_STREAM (p, id);
464 UINT16_TO_STREAM (p, len);
465
466 return (p_buf);
467 }
468
469 /*******************************************************************************
470 **
471 ** Function l2cu_adj_id
472 **
473 ** Description Checks for valid ID based on specified mask
474 ** and adjusts the id if invalid.
475 **
476 ** Returns void
477 **
478 *******************************************************************************/
l2cu_adj_id(tL2C_LCB * p_lcb,UINT8 adj_mask)479 void l2cu_adj_id (tL2C_LCB *p_lcb, UINT8 adj_mask)
480 {
481 if ((adj_mask & L2CAP_ADJ_ZERO_ID) && !p_lcb->id) {
482 p_lcb->id++;
483 }
484 }
485
486 /*******************************************************************************
487 **
488 ** Function l2cu_send_peer_cmd_reject
489 **
490 ** Description Build and send an L2CAP "command reject" message
491 ** to the peer.
492 **
493 ** Returns void
494 **
495 *******************************************************************************/
l2cu_send_peer_cmd_reject(tL2C_LCB * p_lcb,UINT16 reason,UINT8 rem_id,UINT16 p1,UINT16 p2)496 void l2cu_send_peer_cmd_reject (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id,
497 UINT16 p1, UINT16 p2)
498 {
499 UINT16 param_len;
500 BT_HDR *p_buf;
501 UINT8 *p;
502
503 /* Put in L2CAP packet header */
504 if (reason == L2CAP_CMD_REJ_MTU_EXCEEDED) {
505 param_len = 2;
506 } else if (reason == L2CAP_CMD_REJ_INVALID_CID) {
507 param_len = 4;
508 } else {
509 param_len = 0;
510 }
511
512 if ((p_buf = l2cu_build_header (p_lcb, (UINT16) (L2CAP_CMD_REJECT_LEN + param_len), L2CAP_CMD_REJECT, rem_id)) == NULL ) {
513 L2CAP_TRACE_WARNING ("L2CAP - no buffer cmd_rej");
514 return;
515 }
516
517 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
518 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
519
520 UINT16_TO_STREAM (p, reason);
521
522 if (param_len >= 2) {
523 UINT16_TO_STREAM (p, p1);
524 }
525
526 if (param_len >= 4) {
527 UINT16_TO_STREAM (p, p2);
528 }
529
530 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
531 }
532
533
534 /*******************************************************************************
535 **
536 ** Function l2cu_send_peer_connect_req
537 **
538 ** Description Build and send an L2CAP "connection request" message
539 ** to the peer.
540 **
541 ** Returns void
542 **
543 *******************************************************************************/
l2cu_send_peer_connect_req(tL2C_CCB * p_ccb)544 void l2cu_send_peer_connect_req (tL2C_CCB *p_ccb)
545 {
546 BT_HDR *p_buf;
547 UINT8 *p;
548
549 /* Create an identifier for this packet */
550 p_ccb->p_lcb->id++;
551 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
552
553 p_ccb->local_id = p_ccb->p_lcb->id;
554
555 if ((p_buf = l2cu_build_header (p_ccb->p_lcb, L2CAP_CONN_REQ_LEN, L2CAP_CMD_CONN_REQ,
556 p_ccb->local_id)) == NULL) {
557 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
558 return;
559 }
560
561 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
562 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
563
564 UINT16_TO_STREAM (p, p_ccb->p_rcb->real_psm);
565 UINT16_TO_STREAM (p, p_ccb->local_cid);
566
567 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
568 }
569
570
571 /*******************************************************************************
572 **
573 ** Function l2cu_send_peer_connect_rsp
574 **
575 ** Description Build and send an L2CAP "connection response" message
576 ** to the peer.
577 **
578 ** Returns void
579 **
580 *******************************************************************************/
l2cu_send_peer_connect_rsp(tL2C_CCB * p_ccb,UINT16 result,UINT16 status)581 void l2cu_send_peer_connect_rsp (tL2C_CCB *p_ccb, UINT16 result, UINT16 status)
582 {
583 BT_HDR *p_buf;
584 UINT8 *p;
585
586 if (result == L2CAP_CONN_PENDING) {
587 /* if we already sent pending response */
588 if (p_ccb->flags & CCB_FLAG_SENT_PENDING) {
589 return;
590 } else {
591 p_ccb->flags |= CCB_FLAG_SENT_PENDING;
592 }
593 }
594
595 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, p_ccb->remote_id)) == NULL) {
596 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_rsp");
597 return;
598 }
599
600 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
601 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
602
603 UINT16_TO_STREAM (p, p_ccb->local_cid);
604 UINT16_TO_STREAM (p, p_ccb->remote_cid);
605 UINT16_TO_STREAM (p, result);
606 UINT16_TO_STREAM (p, status);
607
608 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
609 }
610
611
612 /*******************************************************************************
613 **
614 ** Function l2cu_reject_connection
615 **
616 ** Description Build and send an L2CAP "connection response neg" message
617 ** to the peer. This function is called when there is no peer
618 ** CCB (non-existant PSM or no resources).
619 **
620 ** Returns void
621 **
622 *******************************************************************************/
l2cu_reject_connection(tL2C_LCB * p_lcb,UINT16 remote_cid,UINT8 rem_id,UINT16 result)623 void l2cu_reject_connection (tL2C_LCB *p_lcb, UINT16 remote_cid, UINT8 rem_id, UINT16 result)
624 {
625 BT_HDR *p_buf;
626 UINT8 *p;
627
628 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, rem_id)) == NULL ) {
629 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
630 return;
631 }
632
633 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
634
635 UINT16_TO_STREAM (p, 0); /* Local CID of 0 */
636 UINT16_TO_STREAM (p, remote_cid);
637 UINT16_TO_STREAM (p, result);
638 UINT16_TO_STREAM (p, 0); /* Status of 0 */
639
640 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
641 }
642
643 /*******************************************************************************
644 **
645 ** Function l2cu_send_peer_config_req
646 **
647 ** Description Build and send an L2CAP "configuration request" message
648 ** to the peer.
649 **
650 ** Returns void
651 **
652 *******************************************************************************/
l2cu_send_peer_config_req(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)653 void l2cu_send_peer_config_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
654 {
655 BT_HDR *p_buf;
656 UINT16 cfg_len = 0;
657 UINT8 *p;
658
659 /* Create an identifier for this packet */
660 p_ccb->p_lcb->id++;
661 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
662
663 p_ccb->local_id = p_ccb->p_lcb->id;
664
665 if (p_cfg->mtu_present) {
666 cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
667 }
668 if (p_cfg->flush_to_present) {
669 cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
670 }
671 if (p_cfg->qos_present) {
672 cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
673 }
674 if (p_cfg->fcr_present) {
675 cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
676 }
677 if (p_cfg->fcs_present) {
678 cfg_len += L2CAP_CFG_FCS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
679 }
680 if (p_cfg->ext_flow_spec_present) {
681 cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
682 }
683
684 if ((p_buf = l2cu_build_header (p_ccb->p_lcb, (UINT16) (L2CAP_CONFIG_REQ_LEN + cfg_len),
685 L2CAP_CMD_CONFIG_REQ, p_ccb->local_id)) == NULL ) {
686 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
687 return;
688 }
689
690 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
691 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
692
693 UINT16_TO_STREAM (p, p_ccb->remote_cid);
694 UINT16_TO_STREAM (p, p_cfg->flags); /* Flags (continuation) */
695
696 /* Now, put the options */
697 if (p_cfg->mtu_present) {
698 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_MTU);
699 UINT8_TO_STREAM (p, L2CAP_CFG_MTU_OPTION_LEN);
700 UINT16_TO_STREAM (p, p_cfg->mtu);
701 }
702 if (p_cfg->flush_to_present) {
703 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FLUSH_TOUT);
704 UINT8_TO_STREAM (p, L2CAP_CFG_FLUSH_OPTION_LEN);
705 UINT16_TO_STREAM (p, p_cfg->flush_to);
706 }
707 if (p_cfg->qos_present) {
708 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_QOS);
709 UINT8_TO_STREAM (p, L2CAP_CFG_QOS_OPTION_LEN);
710 UINT8_TO_STREAM (p, p_cfg->qos.qos_flags);
711 UINT8_TO_STREAM (p, p_cfg->qos.service_type);
712 UINT32_TO_STREAM (p, p_cfg->qos.token_rate);
713 UINT32_TO_STREAM (p, p_cfg->qos.token_bucket_size);
714 UINT32_TO_STREAM (p, p_cfg->qos.peak_bandwidth);
715 UINT32_TO_STREAM (p, p_cfg->qos.latency);
716 UINT32_TO_STREAM (p, p_cfg->qos.delay_variation);
717 }
718 if (p_cfg->fcr_present) {
719 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FCR);
720 UINT8_TO_STREAM (p, L2CAP_CFG_FCR_OPTION_LEN);
721 UINT8_TO_STREAM (p, p_cfg->fcr.mode);
722 UINT8_TO_STREAM (p, p_cfg->fcr.tx_win_sz);
723 UINT8_TO_STREAM (p, p_cfg->fcr.max_transmit);
724 UINT16_TO_STREAM (p, p_cfg->fcr.rtrans_tout);
725 UINT16_TO_STREAM (p, p_cfg->fcr.mon_tout);
726 UINT16_TO_STREAM (p, p_cfg->fcr.mps);
727 }
728
729 if (p_cfg->fcs_present) {
730 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FCS);
731 UINT8_TO_STREAM (p, L2CAP_CFG_FCS_OPTION_LEN);
732 UINT8_TO_STREAM (p, p_cfg->fcs);
733 }
734
735 if (p_cfg->ext_flow_spec_present) {
736 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_EXT_FLOW);
737 UINT8_TO_STREAM (p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
738 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.id);
739 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.stype);
740 UINT16_TO_STREAM (p, p_cfg->ext_flow_spec.max_sdu_size);
741 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.sdu_inter_time);
742 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.access_latency);
743 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.flush_timeout);
744 }
745
746 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
747 }
748
749 /*******************************************************************************
750 **
751 ** Function l2cu_send_peer_config_rsp
752 **
753 ** Description Build and send an L2CAP "configuration response" message
754 ** to the peer.
755 **
756 ** Returns void
757 **
758 *******************************************************************************/
l2cu_send_peer_config_rsp(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)759 void l2cu_send_peer_config_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
760 {
761 BT_HDR *p_buf;
762 UINT16 cfg_len = 0;
763 UINT8 *p;
764
765 /* Create an identifier for this packet */
766 if (p_cfg->mtu_present) {
767 cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
768 }
769 if (p_cfg->flush_to_present) {
770 cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
771 }
772 if (p_cfg->qos_present) {
773 cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
774 }
775 if (p_cfg->fcr_present) {
776 cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
777 }
778 if (p_cfg->ext_flow_spec_present) {
779 cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
780 }
781
782 if ((p_buf = l2cu_build_header (p_ccb->p_lcb, (UINT16)(L2CAP_CONFIG_RSP_LEN + cfg_len),
783 L2CAP_CMD_CONFIG_RSP, p_ccb->remote_id)) == NULL ) {
784 L2CAP_TRACE_WARNING ("L2CAP - no buffer for conn_req");
785 return;
786 }
787
788 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
789
790 UINT16_TO_STREAM (p, p_ccb->remote_cid);
791 UINT16_TO_STREAM (p, p_cfg->flags); /* Flags (continuation) Must match request */
792 UINT16_TO_STREAM (p, p_cfg->result);
793
794 /* Now, put the options */
795 if (p_cfg->mtu_present) {
796 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_MTU);
797 UINT8_TO_STREAM (p, L2CAP_CFG_MTU_OPTION_LEN);
798 UINT16_TO_STREAM (p, p_cfg->mtu);
799 }
800 if (p_cfg->flush_to_present) {
801 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FLUSH_TOUT);
802 UINT8_TO_STREAM (p, L2CAP_CFG_FLUSH_OPTION_LEN);
803 UINT16_TO_STREAM (p, p_cfg->flush_to);
804 }
805 if (p_cfg->qos_present) {
806 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_QOS);
807 UINT8_TO_STREAM (p, L2CAP_CFG_QOS_OPTION_LEN);
808 UINT8_TO_STREAM (p, p_cfg->qos.qos_flags);
809 UINT8_TO_STREAM (p, p_cfg->qos.service_type);
810 UINT32_TO_STREAM (p, p_cfg->qos.token_rate);
811 UINT32_TO_STREAM (p, p_cfg->qos.token_bucket_size);
812 UINT32_TO_STREAM (p, p_cfg->qos.peak_bandwidth);
813 UINT32_TO_STREAM (p, p_cfg->qos.latency);
814 UINT32_TO_STREAM (p, p_cfg->qos.delay_variation);
815 }
816 if (p_cfg->fcr_present) {
817 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_FCR);
818 UINT8_TO_STREAM (p, L2CAP_CFG_FCR_OPTION_LEN);
819 UINT8_TO_STREAM (p, p_cfg->fcr.mode);
820 UINT8_TO_STREAM (p, p_cfg->fcr.tx_win_sz);
821 UINT8_TO_STREAM (p, p_cfg->fcr.max_transmit);
822 UINT16_TO_STREAM (p, p_ccb->our_cfg.fcr.rtrans_tout);
823 UINT16_TO_STREAM (p, p_ccb->our_cfg.fcr.mon_tout);
824 UINT16_TO_STREAM (p, p_cfg->fcr.mps);
825 }
826
827 if (p_cfg->ext_flow_spec_present) {
828 UINT8_TO_STREAM (p, L2CAP_CFG_TYPE_EXT_FLOW);
829 UINT8_TO_STREAM (p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
830 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.id);
831 UINT8_TO_STREAM (p, p_cfg->ext_flow_spec.stype);
832 UINT16_TO_STREAM (p, p_cfg->ext_flow_spec.max_sdu_size);
833 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.sdu_inter_time);
834 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.access_latency);
835 UINT32_TO_STREAM (p, p_cfg->ext_flow_spec.flush_timeout);
836 }
837
838 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
839 }
840
841 /*******************************************************************************
842 **
843 ** Function l2cu_send_peer_config_rej
844 **
845 ** Description Build and send an L2CAP "configuration reject" message
846 ** to the peer.
847 **
848 ** Returns void
849 **
850 *******************************************************************************/
l2cu_send_peer_config_rej(tL2C_CCB * p_ccb,UINT8 * p_data,UINT16 data_len,UINT16 rej_len)851 void l2cu_send_peer_config_rej (tL2C_CCB *p_ccb, UINT8 *p_data, UINT16 data_len, UINT16 rej_len)
852 {
853 BT_HDR *p_buf;
854 UINT16 len, cfg_len, buf_space, len1;
855 UINT8 *p, *p_hci_len, *p_data_end;
856 UINT8 cfg_code;
857
858 L2CAP_TRACE_DEBUG("l2cu_send_peer_config_rej: data_len=%d, rej_len=%d", data_len, rej_len);
859
860
861 len = BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN;
862 len1 = 0xFFFF - len;
863 if (rej_len > len1) {
864 L2CAP_TRACE_ERROR ("L2CAP - cfg_rej pkt size exceeds buffer design max limit.");
865 return;
866 }
867
868 p_buf = (BT_HDR *)osi_malloc (len + rej_len);
869
870 if (!p_buf) {
871 L2CAP_TRACE_ERROR ("L2CAP - no buffer for cfg_rej");
872 return;
873 }
874
875 p_buf->offset = L2CAP_SEND_CMD_OFFSET;
876 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
877
878 /* Put in HCI header - handle + pkt boundary */
879 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
880 if (HCI_NON_FLUSHABLE_PB_SUPPORTED(BTM_ReadLocalFeatures ())) {
881 UINT16_TO_STREAM (p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT)));
882 } else
883 #endif
884 {
885 UINT16_TO_STREAM (p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
886 }
887
888 /* Remember the HCI header length position, and save space for it */
889 p_hci_len = p;
890 p += 2;
891
892 /* Put in L2CAP packet header */
893 UINT16_TO_STREAM (p, L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len);
894 UINT16_TO_STREAM (p, L2CAP_SIGNALLING_CID);
895
896 /* Put in L2CAP command header */
897 UINT8_TO_STREAM (p, L2CAP_CMD_CONFIG_RSP);
898 UINT8_TO_STREAM (p, p_ccb->remote_id);
899
900 UINT16_TO_STREAM (p, L2CAP_CONFIG_RSP_LEN + rej_len);
901
902 UINT16_TO_STREAM (p, p_ccb->remote_cid);
903 UINT16_TO_STREAM (p, 0); /* Flags = 0 (no continuation) */
904 UINT16_TO_STREAM (p, L2CAP_CFG_UNKNOWN_OPTIONS);
905
906 buf_space = rej_len;
907
908 /* Now, put the rejected options */
909 p_data_end = p_data + data_len;
910 while (p_data < p_data_end) {
911 cfg_code = *p_data;
912 cfg_len = *(p_data + 1);
913
914 switch (cfg_code & 0x7F) {
915 /* skip known options */
916 case L2CAP_CFG_TYPE_MTU:
917 case L2CAP_CFG_TYPE_FLUSH_TOUT:
918 case L2CAP_CFG_TYPE_QOS:
919 p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
920 break;
921
922 /* unknown options; copy into rsp if not hints */
923 default:
924 /* sanity check option length */
925 if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= data_len) {
926 if ((cfg_code & 0x80) == 0) {
927 if (buf_space >= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD)) {
928 memcpy(p, p_data, cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
929 p += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
930 buf_space -= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
931 } else {
932 L2CAP_TRACE_WARNING("L2CAP - cfg_rej exceeds allocated buffer");
933 p_data = p_data_end; /* force loop exit */
934 break;
935 }
936 }
937 p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
938 }
939 /* bad length; force loop exit */
940 else {
941 p_data = p_data_end;
942 }
943 break;
944 }
945 }
946
947 len = (UINT16) (p - p_hci_len - 2);
948 UINT16_TO_STREAM (p_hci_len, len);
949
950 p_buf->len = len + 4;
951
952 L2CAP_TRACE_DEBUG ("L2CAP - cfg_rej pkt hci_len=%d, l2cap_len=%d",
953 len, (L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len));
954
955 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
956 }
957
958 /*******************************************************************************
959 **
960 ** Function l2cu_send_peer_disc_req
961 **
962 ** Description Build and send an L2CAP "disconnect request" message
963 ** to the peer.
964 **
965 ** Returns void
966 **
967 *******************************************************************************/
l2cu_send_peer_disc_req(tL2C_CCB * p_ccb)968 void l2cu_send_peer_disc_req (tL2C_CCB *p_ccb)
969 {
970 BT_HDR *p_buf, *p_buf2;
971 UINT8 *p;
972
973 /* Create an identifier for this packet */
974 p_ccb->p_lcb->id++;
975 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
976
977 p_ccb->local_id = p_ccb->p_lcb->id;
978
979 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_DISC_REQ_LEN, L2CAP_CMD_DISC_REQ, p_ccb->local_id)) == NULL) {
980 L2CAP_TRACE_WARNING ("L2CAP - no buffer for disc_req");
981 return;
982 }
983
984 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
985
986 UINT16_TO_STREAM (p, p_ccb->remote_cid);
987 UINT16_TO_STREAM (p, p_ccb->local_cid);
988
989 /* Move all queued data packets to the LCB. In FCR mode, assume the higher
990 layer checks that all buffers are sent before disconnecting.
991 */
992 if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) {
993 while ((p_buf2 = (BT_HDR *)fixed_queue_dequeue(p_ccb->xmit_hold_q, 0)) != NULL) {
994 l2cu_set_acl_hci_header (p_buf2, p_ccb);
995 l2c_link_check_send_pkts (p_ccb->p_lcb, p_ccb, p_buf2);
996 }
997 }
998
999 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
1000 }
1001
1002
1003 /*******************************************************************************
1004 **
1005 ** Function l2cu_send_peer_disc_rsp
1006 **
1007 ** Description Build and send an L2CAP "disconnect response" message
1008 ** to the peer.
1009 **
1010 ** This function is passed the parameters for the disconnect
1011 ** response instead of the CCB address, as it may be called
1012 ** to send a disconnect response when there is no CCB.
1013 **
1014 ** Returns void
1015 **
1016 *******************************************************************************/
l2cu_send_peer_disc_rsp(tL2C_LCB * p_lcb,UINT8 remote_id,UINT16 local_cid,UINT16 remote_cid)1017 void l2cu_send_peer_disc_rsp (tL2C_LCB *p_lcb, UINT8 remote_id, UINT16 local_cid,
1018 UINT16 remote_cid)
1019 {
1020 BT_HDR *p_buf;
1021 UINT8 *p;
1022
1023 if (!p_lcb) {
1024 L2CAP_TRACE_WARNING("lcb already released\n");
1025 return;
1026 }
1027
1028 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_RSP_LEN, L2CAP_CMD_DISC_RSP, remote_id)) == NULL) {
1029 L2CAP_TRACE_WARNING ("L2CAP - no buffer for disc_rsp");
1030 return;
1031 }
1032
1033 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1034
1035 UINT16_TO_STREAM (p, local_cid);
1036 UINT16_TO_STREAM (p, remote_cid);
1037
1038 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1039 }
1040
1041
1042 /*******************************************************************************
1043 **
1044 ** Function l2cu_send_peer_echo_req
1045 **
1046 ** Description Build and send an L2CAP "echo request" message
1047 ** to the peer. Note that we do not currently allow
1048 ** data in the echo request.
1049 **
1050 ** Returns void
1051 **
1052 *******************************************************************************/
l2cu_send_peer_echo_req(tL2C_LCB * p_lcb,UINT8 * p_data,UINT16 data_len)1053 void l2cu_send_peer_echo_req (tL2C_LCB *p_lcb, UINT8 *p_data, UINT16 data_len)
1054 {
1055 BT_HDR *p_buf;
1056 UINT8 *p;
1057
1058 p_lcb->id++;
1059 l2cu_adj_id(p_lcb, L2CAP_ADJ_ZERO_ID); /* check for wrap to '0' */
1060
1061 if ((p_buf = l2cu_build_header(p_lcb, (UINT16) (L2CAP_ECHO_REQ_LEN + data_len), L2CAP_CMD_ECHO_REQ, p_lcb->id)) == NULL) {
1062 L2CAP_TRACE_WARNING ("L2CAP - no buffer for echo_req");
1063 return;
1064 }
1065
1066 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1067
1068 if (data_len) {
1069 ARRAY_TO_STREAM (p, p_data, data_len);
1070 }
1071
1072 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1073 }
1074
1075
1076 /*******************************************************************************
1077 **
1078 ** Function l2cu_send_peer_echo_rsp
1079 **
1080 ** Description Build and send an L2CAP "echo response" message
1081 ** to the peer.
1082 **
1083 ** Returns void
1084 **
1085 *******************************************************************************/
l2cu_send_peer_echo_rsp(tL2C_LCB * p_lcb,UINT8 id,UINT8 * p_data,UINT16 data_len)1086 void l2cu_send_peer_echo_rsp (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len)
1087 {
1088 BT_HDR *p_buf;
1089 UINT8 *p;
1090 UINT16 maxlen;
1091 /* Filter out duplicate IDs or if available buffers are low (intruder checking) */
1092 if (!id || id == p_lcb->cur_echo_id) {
1093 /* Dump this request since it is illegal */
1094 L2CAP_TRACE_WARNING ("L2CAP ignoring duplicate echo request (%d)", id);
1095 return;
1096 } else {
1097 p_lcb->cur_echo_id = id;
1098 }
1099
1100 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic();
1101 uint16_t acl_packet_size = controller_get_interface()->get_acl_packet_size_classic();
1102 /* Don't return data if it does not fit in ACL and L2CAP MTU */
1103 maxlen = (L2CAP_CMD_BUF_SIZE > acl_packet_size) ?
1104 acl_data_size : (UINT16)L2CAP_CMD_BUF_SIZE;
1105 maxlen -= (UINT16)(BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
1106 L2CAP_CMD_OVERHEAD + L2CAP_ECHO_RSP_LEN);
1107
1108 if (data_len > maxlen) {
1109 data_len = 0;
1110 }
1111
1112 if ((p_buf = l2cu_build_header (p_lcb, (UINT16)(L2CAP_ECHO_RSP_LEN + data_len), L2CAP_CMD_ECHO_RSP, id)) == NULL) {
1113 L2CAP_TRACE_WARNING ("L2CAP - no buffer for echo_rsp");
1114 return;
1115 }
1116
1117 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1118 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1119
1120 if (data_len) {
1121 ARRAY_TO_STREAM (p, p_data, data_len);
1122 }
1123
1124 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1125 }
1126
1127 /*******************************************************************************
1128 **
1129 ** Function l2cu_send_peer_info_req
1130 **
1131 ** Description Build and send an L2CAP "info request" message
1132 ** to the peer.
1133 ** Returns void
1134 **
1135 *******************************************************************************/
l2cu_send_peer_info_req(tL2C_LCB * p_lcb,UINT16 info_type)1136 void l2cu_send_peer_info_req (tL2C_LCB *p_lcb, UINT16 info_type)
1137 {
1138 BT_HDR *p_buf;
1139 UINT8 *p;
1140
1141 /* check for wrap and/or BRCM ID */
1142 p_lcb->id++;
1143 l2cu_adj_id(p_lcb, L2CAP_ADJ_ID);
1144
1145 if ((p_buf = l2cu_build_header(p_lcb, 2, L2CAP_CMD_INFO_REQ, p_lcb->id)) == NULL) {
1146 L2CAP_TRACE_WARNING ("L2CAP - no buffer for info_req");
1147 return;
1148 }
1149
1150 L2CAP_TRACE_EVENT ("l2cu_send_peer_info_req: type 0x%04x", info_type);
1151
1152 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1153 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1154
1155 UINT16_TO_STREAM (p, info_type);
1156
1157 p_lcb->w4_info_rsp = TRUE;
1158 btu_start_timer (&p_lcb->info_timer_entry, BTU_TTYPE_L2CAP_INFO, L2CAP_WAIT_INFO_RSP_TOUT);
1159
1160 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1161 }
1162
1163
1164 /*******************************************************************************
1165 **
1166 ** Function l2cu_send_peer_info_rsp
1167 **
1168 ** Description Build and send an L2CAP "info response" message
1169 ** to the peer.
1170 **
1171 ** Returns void
1172 **
1173 *******************************************************************************/
l2cu_send_peer_info_rsp(tL2C_LCB * p_lcb,UINT8 remote_id,UINT16 info_type)1174 void l2cu_send_peer_info_rsp (tL2C_LCB *p_lcb, UINT8 remote_id, UINT16 info_type)
1175 {
1176 BT_HDR *p_buf;
1177 UINT8 *p;
1178 UINT16 len = L2CAP_INFO_RSP_LEN;
1179
1180 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
1181 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1182 && (l2cb.test_info_resp & (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1183 L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_EXT_FLOW_SPEC |
1184 L2CAP_EXTFEA_FIXED_CHNLS | L2CAP_EXTFEA_EXT_WINDOW |
1185 L2CAP_EXTFEA_UCD_RECEPTION )) )
1186 #else
1187 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1188 && (L2CAP_EXTFEA_SUPPORTED_MASK & (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1189 L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS |
1190 L2CAP_EXTFEA_UCD_RECEPTION )) )
1191 #endif
1192 {
1193 len += L2CAP_EXTENDED_FEATURES_ARRAY_SIZE;
1194 } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1195 len += L2CAP_FIXED_CHNL_ARRAY_SIZE;
1196 } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1197 len += L2CAP_CONNLESS_MTU_INFO_SIZE;
1198 }
1199
1200 if ((p_buf = l2cu_build_header(p_lcb, len, L2CAP_CMD_INFO_RSP, remote_id)) == NULL) {
1201 L2CAP_TRACE_WARNING ("L2CAP - no buffer for info_rsp");
1202 return;
1203 }
1204
1205 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1206 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1207
1208 UINT16_TO_STREAM (p, info_type);
1209
1210 #if (L2CAP_CONFORMANCE_TESTING == TRUE)
1211 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1212 && (l2cb.test_info_resp & ( L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE
1213 | L2CAP_EXTFEA_UCD_RECEPTION )) )
1214 #else
1215 if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE)
1216 && (L2CAP_EXTFEA_SUPPORTED_MASK & ( L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE
1217 | L2CAP_EXTFEA_UCD_RECEPTION )) )
1218 #endif
1219 {
1220 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1221 #if (BLE_INCLUDED == TRUE)
1222 if (p_lcb->transport == BT_TRANSPORT_LE) {
1223 /* optional data are not added for now */
1224 UINT32_TO_STREAM (p, L2CAP_BLE_EXTFEA_MASK);
1225 } else
1226 #endif
1227 {
1228 #if L2CAP_CONFORMANCE_TESTING == TRUE
1229 UINT32_TO_STREAM (p, l2cb.test_info_resp);
1230 #else
1231 #if (L2CAP_NUM_FIXED_CHNLS > 0)
1232 UINT32_TO_STREAM (p, L2CAP_EXTFEA_SUPPORTED_MASK | L2CAP_EXTFEA_FIXED_CHNLS);
1233 #else
1234 UINT32_TO_STREAM (p, L2CAP_EXTFEA_SUPPORTED_MASK);
1235 #endif
1236 #endif
1237 }
1238 } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1239 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1240 memset (p, 0, L2CAP_FIXED_CHNL_ARRAY_SIZE);
1241
1242 p[0] = L2CAP_FIXED_CHNL_SIG_BIT;
1243
1244 if ( L2CAP_EXTFEA_SUPPORTED_MASK & L2CAP_EXTFEA_UCD_RECEPTION ) {
1245 p[0] |= L2CAP_FIXED_CHNL_CNCTLESS_BIT;
1246 }
1247
1248 #if (L2CAP_NUM_FIXED_CHNLS > 0)
1249 {
1250 int xx;
1251
1252 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++)
1253 if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
1254 p[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] |= 1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8);
1255 }
1256 }
1257 #endif
1258 } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1259 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1260 UINT16_TO_STREAM (p, L2CAP_UCD_MTU);
1261 } else {
1262 UINT16_TO_STREAM (p, L2CAP_INFO_RESP_RESULT_NOT_SUPPORTED); /* 'not supported' */
1263 }
1264
1265 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
1266 }
1267
1268 /******************************************************************************
1269 **
1270 ** Function l2cu_enqueue_ccb
1271 **
1272 ** Description queue CCB by priority. The first CCB is highest priority and
1273 ** is served at first. The CCB is queued to an LLCB or an LCB.
1274 **
1275 ** Returns None
1276 **
1277 *******************************************************************************/
l2cu_enqueue_ccb(tL2C_CCB * p_ccb)1278 void l2cu_enqueue_ccb (tL2C_CCB *p_ccb)
1279 {
1280 tL2C_CCB *p_ccb1;
1281 tL2C_CCB_Q *p_q = NULL;
1282
1283 /* Find out which queue the channel is on
1284 */
1285 if (p_ccb->p_lcb != NULL) {
1286 p_q = &p_ccb->p_lcb->ccb_queue;
1287 }
1288
1289 if ( (!p_ccb->in_use) || (p_q == NULL) ) {
1290 L2CAP_TRACE_ERROR ("l2cu_enqueue_ccb CID: 0x%04x ERROR in_use: %u p_lcb: %p",
1291 p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb);
1292 return;
1293 }
1294
1295 L2CAP_TRACE_DEBUG ("l2cu_enqueue_ccb CID: 0x%04x priority: %d",
1296 p_ccb->local_cid, p_ccb->ccb_priority);
1297
1298 /* If the queue is empty, we go at the front */
1299 if (!p_q->p_first_ccb) {
1300 p_q->p_first_ccb = p_q->p_last_ccb = p_ccb;
1301 p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1302 } else {
1303 p_ccb1 = p_q->p_first_ccb;
1304
1305 while (p_ccb1 != NULL) {
1306 /* Insert new ccb at the end of the same priority. Lower number, higher priority */
1307 if (p_ccb->ccb_priority < p_ccb1->ccb_priority) {
1308 /* Are we at the head of the queue ? */
1309 if (p_ccb1 == p_q->p_first_ccb) {
1310 p_q->p_first_ccb = p_ccb;
1311 } else {
1312 p_ccb1->p_prev_ccb->p_next_ccb = p_ccb;
1313 }
1314
1315 p_ccb->p_next_ccb = p_ccb1;
1316 p_ccb->p_prev_ccb = p_ccb1->p_prev_ccb;
1317 p_ccb1->p_prev_ccb = p_ccb;
1318 break;
1319 }
1320
1321 p_ccb1 = p_ccb1->p_next_ccb;
1322 }
1323
1324 /* If we are lower then anyone in the list, we go at the end */
1325 if (!p_ccb1) {
1326 /* add new ccb at the end of the list */
1327 p_q->p_last_ccb->p_next_ccb = p_ccb;
1328
1329 p_ccb->p_next_ccb = NULL;
1330 p_ccb->p_prev_ccb = p_q->p_last_ccb;
1331 p_q->p_last_ccb = p_ccb;
1332 }
1333 }
1334
1335 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1336 /* Adding CCB into round robin service table of its LCB */
1337 if (p_ccb->p_lcb != NULL) {
1338 /* if this is the first channel in this priority group */
1339 if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0 ) {
1340 /* Set the first channel to this CCB */
1341 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1342 /* Set the next serving channel in this group to this CCB */
1343 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1344 /* Initialize quota of this priority group based on its priority */
1345 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota = L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1346 }
1347 /* increase number of channels in this group */
1348 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb++;
1349 }
1350 #endif
1351
1352 }
1353
1354 /******************************************************************************
1355 **
1356 ** Function l2cu_dequeue_ccb
1357 **
1358 ** Description dequeue CCB from a queue
1359 **
1360 ** Returns -
1361 **
1362 *******************************************************************************/
l2cu_dequeue_ccb(tL2C_CCB * p_ccb)1363 void l2cu_dequeue_ccb (tL2C_CCB *p_ccb)
1364 {
1365 tL2C_CCB_Q *p_q = NULL;
1366
1367 L2CAP_TRACE_DEBUG ("l2cu_dequeue_ccb CID: 0x%04x", p_ccb->local_cid);
1368
1369 /* Find out which queue the channel is on
1370 */
1371 if (p_ccb->p_lcb != NULL) {
1372 p_q = &p_ccb->p_lcb->ccb_queue;
1373 }
1374
1375 if ( (!p_ccb->in_use) || (p_q == NULL) || (p_q->p_first_ccb == NULL) ) {
1376 L2CAP_TRACE_ERROR ("l2cu_dequeue_ccb CID: 0x%04x ERROR in_use: %u p_lcb: %p p_q: %p p_q->p_first_ccb: %p",
1377 p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb, p_q, p_q ? p_q->p_first_ccb : 0);
1378 return;
1379 }
1380
1381 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1382 /* Removing CCB from round robin service table of its LCB */
1383 if (p_ccb->p_lcb != NULL) {
1384 /* decrease number of channels in this priority group */
1385 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb--;
1386
1387 /* if it was the last channel in the priority group */
1388 if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0 ) {
1389 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1390 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1391 } else {
1392 /* if it is the first channel of this group */
1393 if ( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb == p_ccb ) {
1394 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb->p_next_ccb;
1395 }
1396 /* if it is the next serving channel of this group */
1397 if ( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb == p_ccb ) {
1398 /* simply, start serving from the first channel */
1399 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb
1400 = p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb;
1401 }
1402 }
1403 }
1404 #endif
1405
1406 if (p_ccb == p_q->p_first_ccb) {
1407 /* We are removing the first in a queue */
1408 p_q->p_first_ccb = p_ccb->p_next_ccb;
1409
1410 if (p_q->p_first_ccb) {
1411 p_q->p_first_ccb->p_prev_ccb = NULL;
1412 } else {
1413 p_q->p_last_ccb = NULL;
1414 }
1415 } else if (p_ccb == p_q->p_last_ccb) {
1416 /* We are removing the last in a queue */
1417 p_q->p_last_ccb = p_ccb->p_prev_ccb;
1418 p_q->p_last_ccb->p_next_ccb = NULL;
1419 } else {
1420 /* In the middle of a chain. */
1421 p_ccb->p_prev_ccb->p_next_ccb = p_ccb->p_next_ccb;
1422 p_ccb->p_next_ccb->p_prev_ccb = p_ccb->p_prev_ccb;
1423 }
1424
1425 p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1426 }
1427
1428 /******************************************************************************
1429 **
1430 ** Function l2cu_change_pri_ccb
1431 **
1432 ** Description
1433 **
1434 ** Returns -
1435 **
1436 *******************************************************************************/
l2cu_change_pri_ccb(tL2C_CCB * p_ccb,tL2CAP_CHNL_PRIORITY priority)1437 void l2cu_change_pri_ccb (tL2C_CCB *p_ccb, tL2CAP_CHNL_PRIORITY priority)
1438 {
1439 if (p_ccb->ccb_priority != priority) {
1440 /* If CCB is not the only guy on the queue */
1441 if ( (p_ccb->p_next_ccb != NULL) || (p_ccb->p_prev_ccb != NULL) ) {
1442 L2CAP_TRACE_DEBUG ("Update CCB list in logical link");
1443
1444 /* Remove CCB from queue and re-queue it at new priority */
1445 l2cu_dequeue_ccb (p_ccb);
1446
1447 p_ccb->ccb_priority = priority;
1448 l2cu_enqueue_ccb (p_ccb);
1449 }
1450 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1451 else {
1452 /* If CCB is the only guy on the queue, no need to re-enqueue */
1453 /* update only round robin service data */
1454 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 0;
1455 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1456 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1457
1458 p_ccb->ccb_priority = priority;
1459
1460 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1461 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1462 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota = L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1463 p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 1;
1464 }
1465 #endif
1466 }
1467 }
1468
1469 /*******************************************************************************
1470 **
1471 ** Function l2cu_allocate_ccb
1472 **
1473 ** Description This function allocates a Channel Control Block and
1474 ** attaches it to a link control block. The local CID
1475 ** is also assigned.
1476 **
1477 ** Returns pointer to CCB, or NULL if none
1478 **
1479 *******************************************************************************/
1480 bool l2cu_find_ccb_in_list(void *p_ccb_node, void *p_local_cid);
l2cu_allocate_ccb(tL2C_LCB * p_lcb,UINT16 cid)1481 tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid)
1482 {
1483 tL2C_CCB *p_ccb = NULL;
1484 uint16_t tmp_cid = L2CAP_BASE_APPL_CID;
1485 L2CAP_TRACE_DEBUG ("l2cu_allocate_ccb: cid 0x%04x", cid);
1486
1487 p_ccb = l2cu_find_free_ccb ();
1488 if(p_ccb == NULL) {
1489 if (list_length(l2cb.p_ccb_pool) < MAX_L2CAP_CHANNELS) {
1490 p_ccb = (tL2C_CCB *)osi_malloc(sizeof(tL2C_CCB));
1491
1492 if (p_ccb) {
1493 memset (p_ccb, 0, sizeof(tL2C_CCB));
1494 list_append(l2cb.p_ccb_pool, p_ccb);
1495 }
1496 }
1497 }
1498 if (p_ccb == NULL) {
1499 return (NULL);
1500 }
1501
1502 p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1503
1504 p_ccb->in_use = TRUE;
1505
1506 /* Get a CID for the connection */
1507 for (tmp_cid = L2CAP_BASE_APPL_CID; tmp_cid < MAX_L2CAP_CHANNELS + L2CAP_BASE_APPL_CID; tmp_cid++) {
1508 if (list_foreach(l2cb.p_ccb_pool, l2cu_find_ccb_in_list, &tmp_cid) == NULL) {
1509 break;
1510 }
1511 }
1512 assert(tmp_cid != MAX_L2CAP_CHANNELS + L2CAP_BASE_APPL_CID);
1513 p_ccb->local_cid = tmp_cid;
1514 p_ccb->p_lcb = p_lcb;
1515 p_ccb->p_rcb = NULL;
1516 p_ccb->should_free_rcb = false;
1517
1518 /* Set priority then insert ccb into LCB queue (if we have an LCB) */
1519 p_ccb->ccb_priority = L2CAP_CHNL_PRIORITY_LOW;
1520
1521 if (p_lcb) {
1522 l2cu_enqueue_ccb (p_ccb);
1523 }
1524
1525 /* clear what peer wants to configure */
1526 p_ccb->peer_cfg_bits = 0;
1527
1528 /* Put in default values for configuration */
1529 memset (&p_ccb->our_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1530 memset (&p_ccb->peer_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1531
1532 /* Put in default values for local/peer configurations */
1533 p_ccb->our_cfg.flush_to = p_ccb->peer_cfg.flush_to = L2CAP_DEFAULT_FLUSH_TO;
1534 p_ccb->our_cfg.mtu = p_ccb->peer_cfg.mtu = L2CAP_DEFAULT_MTU;
1535 p_ccb->our_cfg.qos.service_type = p_ccb->peer_cfg.qos.service_type = L2CAP_DEFAULT_SERV_TYPE;
1536 p_ccb->our_cfg.qos.token_rate = p_ccb->peer_cfg.qos.token_rate = L2CAP_DEFAULT_TOKEN_RATE;
1537 p_ccb->our_cfg.qos.token_bucket_size = p_ccb->peer_cfg.qos.token_bucket_size = L2CAP_DEFAULT_BUCKET_SIZE;
1538 p_ccb->our_cfg.qos.peak_bandwidth = p_ccb->peer_cfg.qos.peak_bandwidth = L2CAP_DEFAULT_PEAK_BANDWIDTH;
1539 p_ccb->our_cfg.qos.latency = p_ccb->peer_cfg.qos.latency = L2CAP_DEFAULT_LATENCY;
1540 p_ccb->our_cfg.qos.delay_variation = p_ccb->peer_cfg.qos.delay_variation = L2CAP_DEFAULT_DELAY;
1541
1542 p_ccb->bypass_fcs = 0;
1543 memset (&p_ccb->ertm_info, 0, sizeof(tL2CAP_ERTM_INFO));
1544 p_ccb->peer_cfg_already_rejected = FALSE;
1545 p_ccb->fcr_cfg_tries = L2CAP_MAX_FCR_CFG_TRIES;
1546
1547 /* stop and release timers */
1548 btu_free_quick_timer(&p_ccb->fcrb.ack_timer);
1549 memset(&p_ccb->fcrb.ack_timer, 0, sizeof(TIMER_LIST_ENT));
1550 p_ccb->fcrb.ack_timer.param = (TIMER_PARAM_TYPE)p_ccb;
1551
1552 btu_free_quick_timer(&p_ccb->fcrb.mon_retrans_timer);
1553 memset(&p_ccb->fcrb.mon_retrans_timer, 0, sizeof(TIMER_LIST_ENT));
1554 p_ccb->fcrb.mon_retrans_timer.param = (TIMER_PARAM_TYPE)p_ccb;
1555
1556 // btla-specific ++
1557 /* CSP408639 Fix: When L2CAP send amp move channel request or receive
1558 * L2CEVT_AMP_MOVE_REQ do following sequence. Send channel move
1559 * request -> Stop retrans/monitor timer -> Change channel state to CST_AMP_MOVING. */
1560 // btla-specific --
1561
1562 #if (CLASSIC_BT_INCLUDED == TRUE)
1563 l2c_fcr_free_timer (p_ccb);
1564 #endif ///CLASSIC_BT_INCLUDED == TRUE
1565
1566 #if BT_SDP_BQB_INCLUDED
1567 if (l2cap_bqb_ertm_mode_included_flag) {
1568 p_ccb->ertm_info.preferred_mode = L2CAP_FCR_ERTM_MODE;
1569 p_ccb->ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM;
1570 } else
1571 #endif /* BT_SDP_BQB_INCLUDED */
1572 {
1573 p_ccb->ertm_info.preferred_mode = L2CAP_FCR_BASIC_MODE; /* Default mode for channel is basic mode */
1574 p_ccb->ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_BASIC|L2CAP_FCR_CHAN_OPT_ERTM;
1575 }
1576 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
1577 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
1578 p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
1579 p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
1580 p_ccb->max_rx_mtu = L2CAP_MTU_SIZE;
1581 p_ccb->tx_mps = L2CAP_FCR_TX_BUF_SIZE - 32;
1582
1583 p_ccb->xmit_hold_q = fixed_queue_new(QUEUE_SIZE_MAX);
1584 #if (CLASSIC_BT_INCLUDED == TRUE)
1585 p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(QUEUE_SIZE_MAX);
1586 p_ccb->fcrb.retrans_q = fixed_queue_new(QUEUE_SIZE_MAX);
1587 p_ccb->fcrb.waiting_for_ack_q = fixed_queue_new(QUEUE_SIZE_MAX);
1588 #endif ///CLASSIC_BT_INCLUDED == TRUE
1589
1590 p_ccb->cong_sent = FALSE;
1591 p_ccb->buff_quota = 2; /* This gets set after config */
1592
1593 /* If CCB was reserved Config_Done can already have some value */
1594 if (cid == 0) {
1595 p_ccb->config_done = 0;
1596 } else {
1597 L2CAP_TRACE_DEBUG ("l2cu_allocate_ccb: cid 0x%04x config_done:0x%x", cid, p_ccb->config_done);
1598 }
1599
1600 p_ccb->chnl_state = CST_CLOSED;
1601 p_ccb->flags = 0;
1602 p_ccb->tx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1603 p_ccb->rx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1604
1605 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
1606 p_ccb->is_flushable = FALSE;
1607 #endif
1608
1609 btu_free_timer(&p_ccb->timer_entry);
1610 memset(&p_ccb->timer_entry, 0, sizeof(TIMER_LIST_ENT));
1611 p_ccb->timer_entry.param = (TIMER_PARAM_TYPE)p_ccb;
1612 p_ccb->timer_entry.in_use = 0;
1613
1614 l2c_link_adjust_chnl_allocation ();
1615
1616 return (p_ccb);
1617 }
1618
1619 /*******************************************************************************
1620 **
1621 ** Function l2cu_start_post_bond_timer
1622 **
1623 ** Description This function starts the ACL Link inactivity timer after
1624 ** dedicated bonding
1625 ** This timer can be longer than the normal link inactivity
1626 ** timer for some platforms.
1627 **
1628 ** Returns BOOLEAN - TRUE if idle timer started or disconnect initiated
1629 ** FALSE if there's one or more pending CCB's exist
1630 **
1631 *******************************************************************************/
l2cu_start_post_bond_timer(UINT16 handle)1632 BOOLEAN l2cu_start_post_bond_timer (UINT16 handle)
1633 {
1634 UINT16 timeout;
1635 tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
1636
1637 if (!p_lcb) {
1638 return (TRUE);
1639 }
1640
1641 p_lcb->is_bonding = FALSE;
1642
1643 /* Only start timer if no control blocks allocated */
1644 if (p_lcb->ccb_queue.p_first_ccb != NULL) {
1645 return (FALSE);
1646 }
1647
1648 /* If no channels on the connection, start idle timeout */
1649 if ( (p_lcb->link_state == LST_CONNECTED) || (p_lcb->link_state == LST_CONNECTING) || (p_lcb->link_state == LST_DISCONNECTING) ) {
1650 if (p_lcb->idle_timeout == 0) {
1651 if (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) {
1652 p_lcb->link_state = LST_DISCONNECTING;
1653 timeout = L2CAP_LINK_DISCONNECT_TOUT;
1654 } else {
1655 timeout = BT_1SEC_TIMEOUT;
1656 }
1657 } else {
1658 timeout = L2CAP_BONDING_TIMEOUT;
1659 }
1660
1661 if (timeout != 0xFFFF) {
1662 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, timeout);
1663 }
1664
1665 return (TRUE);
1666 }
1667
1668 return (FALSE);
1669 }
1670
1671 /*******************************************************************************
1672 **
1673 ** Function l2cu_release_ccb
1674 **
1675 ** Description This function releases a Channel Control Block. The timer
1676 ** is stopped, any attached buffers freed, and the CCB is removed
1677 ** from the link control block.
1678 **
1679 ** Returns void
1680 **
1681 *******************************************************************************/
l2cu_release_ccb(tL2C_CCB * p_ccb)1682 void l2cu_release_ccb (tL2C_CCB *p_ccb)
1683 {
1684 tL2C_LCB *p_lcb = p_ccb->p_lcb;
1685 tL2C_RCB *p_rcb = p_ccb->p_rcb;
1686 L2CAP_TRACE_DEBUG ("l2cu_release_ccb: cid 0x%04x in_use: %u", p_ccb->local_cid, p_ccb->in_use);
1687
1688 /* If already released, could be race condition */
1689 if (!p_ccb->in_use) {
1690 return;
1691 }
1692 #if BLE_INCLUDED == TRUE
1693 if (p_lcb->transport == BT_TRANSPORT_LE) {
1694 /* Take samephore to avoid race condition */
1695 l2ble_update_att_acl_pkt_num(L2CA_BUFF_FREE, NULL);
1696 }
1697 #endif
1698 #if (SDP_INCLUDED == TRUE)
1699 if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) {
1700 btm_sec_clr_service_by_psm(p_rcb->psm);
1701 }
1702 #endif ///SMP_INCLUDED == TRUE
1703 if (p_ccb->should_free_rcb) {
1704 osi_free(p_rcb);
1705 p_ccb->p_rcb = NULL;
1706 p_ccb->should_free_rcb = false;
1707 }
1708 if (p_lcb) {
1709 btm_sec_clr_temp_auth_service (p_lcb->remote_bd_addr);
1710 }
1711
1712 /* Stop and free the timer */
1713 btu_free_timer (&p_ccb->timer_entry);
1714
1715 fixed_queue_free(p_ccb->xmit_hold_q, osi_free_func);
1716 p_ccb->xmit_hold_q = NULL;
1717 #if (CLASSIC_BT_INCLUDED == TRUE)
1718 fixed_queue_free(p_ccb->fcrb.srej_rcv_hold_q, osi_free_func);
1719 fixed_queue_free(p_ccb->fcrb.retrans_q, osi_free_func);
1720 fixed_queue_free(p_ccb->fcrb.waiting_for_ack_q, osi_free_func);
1721 p_ccb->fcrb.srej_rcv_hold_q = NULL;
1722 p_ccb->fcrb.retrans_q = NULL;
1723 p_ccb->fcrb.waiting_for_ack_q = NULL;
1724 #endif ///CLASSIC_BT_INCLUDED == TRUE
1725
1726
1727 #if (CLASSIC_BT_INCLUDED == TRUE)
1728 l2c_fcr_cleanup (p_ccb);
1729 #endif ///CLASSIC_BT_INCLUDED == TRUE
1730 /* Channel may not be assigned to any LCB if it was just pre-reserved */
1731 if ( (p_lcb) &&
1732 ( (p_ccb->local_cid >= L2CAP_BASE_APPL_CID)
1733 #if (L2CAP_UCD_INCLUDED == TRUE)
1734 || (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID)
1735 #endif
1736 )
1737 ) {
1738 l2cu_dequeue_ccb (p_ccb);
1739
1740 /* Delink the CCB from the LCB */
1741 p_ccb->p_lcb = NULL;
1742 }
1743
1744
1745 /* Flag as not in use */
1746 p_ccb->in_use = FALSE;
1747
1748 /* If no channels on the connection, start idle timeout */
1749 if ((p_lcb) && p_lcb->in_use && (p_lcb->link_state == LST_CONNECTED)) {
1750 if (!p_lcb->ccb_queue.p_first_ccb) {
1751 l2cu_no_dynamic_ccbs (p_lcb);
1752 } else {
1753 /* Link is still active, adjust channel quotas. */
1754 l2c_link_adjust_chnl_allocation ();
1755 }
1756 }
1757 }
1758
1759 /*******************************************************************************
1760 **
1761 ** Function l2cu_find_ccb_by_remote_cid
1762 **
1763 ** Description Look through all active CCBs on a link for a match based
1764 ** on the remote CID.
1765 **
1766 ** Returns pointer to matched CCB, or NULL if no match
1767 **
1768 *******************************************************************************/
l2cu_find_ccb_by_remote_cid(tL2C_LCB * p_lcb,UINT16 remote_cid)1769 tL2C_CCB *l2cu_find_ccb_by_remote_cid (tL2C_LCB *p_lcb, UINT16 remote_cid)
1770 {
1771 tL2C_CCB *p_ccb;
1772
1773 /* If LCB is NULL, look through all active links */
1774 if (!p_lcb) {
1775 return NULL;
1776 } else {
1777 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
1778 if ((p_ccb->in_use) && (p_ccb->remote_cid == remote_cid)) {
1779 return (p_ccb);
1780 }
1781 }
1782
1783 /* If here, no match found */
1784 return (NULL);
1785 }
1786
1787 /*******************************************************************************
1788 **
1789 ** Function l2cu_allocate_rcb
1790 **
1791 ** Description Look through the Registration Control Blocks for a free
1792 ** one.
1793 **
1794 ** Returns Pointer to the RCB or NULL if not found
1795 **
1796 *******************************************************************************/
l2cu_allocate_rcb(UINT16 psm)1797 tL2C_RCB *l2cu_allocate_rcb (UINT16 psm)
1798 {
1799 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
1800 UINT16 xx;
1801
1802 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1803 if (!p_rcb->in_use) {
1804 p_rcb->in_use = TRUE;
1805 p_rcb->psm = psm;
1806 #if (L2CAP_UCD_INCLUDED == TRUE)
1807 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
1808 #endif
1809 return (p_rcb);
1810 }
1811 }
1812
1813 /* If here, no free RCB found */
1814 return (NULL);
1815 }
1816
1817 #if (BLE_INCLUDED == TRUE)
1818 /*******************************************************************************
1819 **
1820 ** Function l2cu_allocate_ble_rcb
1821 **
1822 ** Description Look through the BLE Registration Control Blocks for a free
1823 ** one.
1824 **
1825 ** Returns Pointer to the BLE RCB or NULL if not found
1826 **
1827 *******************************************************************************/
l2cu_allocate_ble_rcb(UINT16 psm)1828 tL2C_RCB *l2cu_allocate_ble_rcb (UINT16 psm)
1829 {
1830 tL2C_RCB *p_rcb = &l2cb.ble_rcb_pool[0];
1831 UINT16 xx;
1832
1833 for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++)
1834 {
1835 if (!p_rcb->in_use)
1836 {
1837 p_rcb->in_use = TRUE;
1838 p_rcb->psm = psm;
1839 #if (L2CAP_UCD_INCLUDED == TRUE)
1840 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
1841 #endif
1842 return (p_rcb);
1843 }
1844 }
1845
1846 /* If here, no free RCB found */
1847 return (NULL);
1848 }
1849 #endif ///BLE_INCLUDED == TRUE
1850
1851 /*******************************************************************************
1852 **
1853 ** Function l2cu_release_rcb
1854 **
1855 ** Description Mark an RCB as no longet in use
1856 **
1857 ** Returns void
1858 **
1859 *******************************************************************************/
l2cu_release_rcb(tL2C_RCB * p_rcb)1860 void l2cu_release_rcb (tL2C_RCB *p_rcb)
1861 {
1862 p_rcb->in_use = FALSE;
1863 p_rcb->psm = 0;
1864 }
1865
1866
1867 /*******************************************************************************
1868 **
1869 ** Function l2cu_disconnect_chnl
1870 **
1871 ** Description Disconnect a channel. Typically, this is due to either
1872 ** receiving a bad configuration, bad packet or max_retries expiring.
1873 **
1874 *******************************************************************************/
l2cu_disconnect_chnl(tL2C_CCB * p_ccb)1875 void l2cu_disconnect_chnl (tL2C_CCB *p_ccb)
1876 {
1877 UINT16 local_cid = p_ccb->local_cid;
1878
1879 if (local_cid >= L2CAP_BASE_APPL_CID) {
1880 tL2CA_DISCONNECT_IND_CB *p_disc_cb = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
1881
1882 L2CAP_TRACE_WARNING ("L2CAP - disconnect_chnl CID: 0x%04x", local_cid);
1883
1884 l2cu_send_peer_disc_req (p_ccb);
1885
1886 l2cu_release_ccb (p_ccb);
1887
1888 (*p_disc_cb)(local_cid, FALSE);
1889 } else {
1890 /* failure on the AMP channel, probably need to disconnect ACL */
1891 L2CAP_TRACE_ERROR ("L2CAP - disconnect_chnl CID: 0x%04x Ignored", local_cid);
1892 }
1893 }
1894
1895
1896 /*******************************************************************************
1897 **
1898 ** Function l2cu_find_rcb_by_psm
1899 **
1900 ** Description Look through the Registration Control Blocks to see if
1901 ** anyone registered to handle the PSM in question
1902 **
1903 ** Returns Pointer to the RCB or NULL if not found
1904 **
1905 *******************************************************************************/
l2cu_find_rcb_by_psm(UINT16 psm)1906 tL2C_RCB *l2cu_find_rcb_by_psm (UINT16 psm)
1907 {
1908 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
1909 UINT16 xx;
1910
1911 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1912 if ((p_rcb->in_use) && (p_rcb->psm == psm)) {
1913 return (p_rcb);
1914 }
1915 }
1916
1917 /* If here, no match found */
1918 return (NULL);
1919 }
1920
1921 #if (BLE_INCLUDED == TRUE)
1922 /*******************************************************************************
1923 **
1924 ** Function l2cu_find_ble_rcb_by_psm
1925 **
1926 ** Description Look through the BLE Registration Control Blocks to see if
1927 ** anyone registered to handle the PSM in question
1928 **
1929 ** Returns Pointer to the BLE RCB or NULL if not found
1930 **
1931 *******************************************************************************/
l2cu_find_ble_rcb_by_psm(UINT16 psm)1932 tL2C_RCB *l2cu_find_ble_rcb_by_psm (UINT16 psm)
1933 {
1934 tL2C_RCB *p_rcb = &l2cb.ble_rcb_pool[0];
1935 UINT16 xx;
1936
1937 for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++)
1938 {
1939 if ((p_rcb->in_use) && (p_rcb->psm == psm)) {
1940 return (p_rcb);
1941 }
1942 }
1943
1944 /* If here, no match found */
1945 return (NULL);
1946 }
1947 #endif ///BLE_INCLUDED == TRUE
1948
1949 #if (L2CAP_COC_INCLUDED == TRUE)
1950 /*******************************************************************************
1951 **
1952 ** Function l2cu_process_peer_cfg_req
1953 **
1954 ** Description This function is called when the peer sends us a "config request"
1955 ** message. It extracts the configuration of interest and saves
1956 ** it in the CCB.
1957 **
1958 ** Note: Negotiation of the FCR channel type is handled internally,
1959 ** all others are passed to the upper layer.
1960 **
1961 ** Returns UINT8 - L2CAP_PEER_CFG_OK if passed to upper layer,
1962 ** L2CAP_PEER_CFG_UNACCEPTABLE if automatically responded to
1963 ** because parameters are unnacceptable from a specification
1964 ** point of view.
1965 ** L2CAP_PEER_CFG_DISCONNECT if no compatible channel modes
1966 ** between the two devices, and shall be closed.
1967 **
1968 *******************************************************************************/
l2cu_process_peer_cfg_req(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)1969 UINT8 l2cu_process_peer_cfg_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
1970 {
1971 BOOLEAN mtu_ok = TRUE;
1972 BOOLEAN qos_type_ok = TRUE;
1973 BOOLEAN flush_to_ok = TRUE;
1974 BOOLEAN fcr_ok = TRUE;
1975 #if (CLASSIC_BT_INCLUDED == TRUE)
1976 UINT8 fcr_status;
1977 #endif ///CLASSIC_BT_INCLUDED == TRUE
1978 /* Ignore FCR parameters for basic mode */
1979 if (!p_cfg->fcr_present) {
1980 p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
1981 }
1982
1983 /* Save the MTU that our peer can receive */
1984 if (p_cfg->mtu_present) {
1985 /* Make sure MTU is at least the minimum */
1986 if (p_cfg->mtu >= L2CAP_MIN_MTU) {
1987 /* In basic mode, limit the MTU to our buffer size */
1988 if ( (p_cfg->fcr_present == FALSE) && (p_cfg->mtu > L2CAP_MTU_SIZE) ) {
1989 p_cfg->mtu = L2CAP_MTU_SIZE;
1990 }
1991
1992 /* Save the accepted value in case of renegotiation */
1993 p_ccb->peer_cfg.mtu = p_cfg->mtu;
1994 p_ccb->peer_cfg.mtu_present = TRUE;
1995 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_MTU;
1996 } else { /* Illegal MTU value */
1997 p_cfg->mtu = L2CAP_MIN_MTU;
1998 mtu_ok = FALSE;
1999 }
2000 }
2001 /* Reload mtu from a previously accepted config request */
2002 else if (p_ccb->peer_cfg.mtu_present) {
2003 p_cfg->mtu_present = TRUE;
2004 p_cfg->mtu = p_ccb->peer_cfg.mtu;
2005 }
2006
2007 /* Verify that the flush timeout is a valid value (0 is illegal) */
2008 if (p_cfg->flush_to_present) {
2009 if (!p_cfg->flush_to) {
2010 p_cfg->flush_to = 0xFFFF; /* Infinite retransmissions (spec default) */
2011 flush_to_ok = FALSE;
2012 } else { /* Save the accepted value in case of renegotiation */
2013 p_ccb->peer_cfg.flush_to_present = TRUE;
2014 p_ccb->peer_cfg.flush_to = p_cfg->flush_to;
2015 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FLUSH_TO;
2016 }
2017 }
2018 /* Reload flush_to from a previously accepted config request */
2019 else if (p_ccb->peer_cfg.flush_to_present) {
2020 p_cfg->flush_to_present = TRUE;
2021 p_cfg->flush_to = p_ccb->peer_cfg.flush_to;
2022 }
2023
2024 /* Save the QOS settings the the peer is using */
2025 if (p_cfg->qos_present) {
2026 /* Make sure service type is not a reserved value; otherwise let upper
2027 layer decide if acceptable
2028 */
2029 if (p_cfg->qos.service_type <= GUARANTEED) {
2030 p_ccb->peer_cfg.qos = p_cfg->qos;
2031 p_ccb->peer_cfg.qos_present = TRUE;
2032 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_QOS;
2033 } else { /* Illegal service type value */
2034 p_cfg->qos.service_type = BEST_EFFORT;
2035 qos_type_ok = FALSE;
2036 }
2037 }
2038 /* Reload QOS from a previously accepted config request */
2039 else if (p_ccb->peer_cfg.qos_present) {
2040 p_cfg->qos_present = TRUE;
2041 p_cfg->qos = p_ccb->peer_cfg.qos;
2042 }
2043 #if (CLASSIC_BT_INCLUDED == TRUE)
2044 if ((fcr_status = l2c_fcr_process_peer_cfg_req (p_ccb, p_cfg)) == L2CAP_PEER_CFG_DISCONNECT) {
2045 /* Notify caller to disconnect the channel (incompatible modes) */
2046 p_cfg->result = L2CAP_CFG_FAILED_NO_REASON;
2047 p_cfg->mtu_present = p_cfg->qos_present = p_cfg->flush_to_present = 0;
2048
2049 return (L2CAP_PEER_CFG_DISCONNECT);
2050 }
2051
2052 fcr_ok = (fcr_status == L2CAP_PEER_CFG_OK);
2053 #endif ///CLASSIC_BT_INCLUDED == TRUE
2054
2055 /* Return any unacceptable parameters */
2056 if (mtu_ok && flush_to_ok && qos_type_ok && fcr_ok) {
2057 l2cu_adjust_out_mps (p_ccb);
2058 return (L2CAP_PEER_CFG_OK);
2059 } else {
2060 p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
2061
2062 if (mtu_ok) {
2063 p_cfg->mtu_present = FALSE;
2064 }
2065 if (flush_to_ok) {
2066 p_cfg->flush_to_present = FALSE;
2067 }
2068 if (qos_type_ok) {
2069 p_cfg->qos_present = FALSE;
2070 }
2071 if (fcr_ok) {
2072 p_cfg->fcr_present = FALSE;
2073 }
2074
2075 return (L2CAP_PEER_CFG_UNACCEPTABLE);
2076 }
2077 }
2078
2079
2080 /*******************************************************************************
2081 **
2082 ** Function l2cu_process_peer_cfg_rsp
2083 **
2084 ** Description This function is called when the peer sends us a "config response"
2085 ** message. It extracts the configuration of interest and saves
2086 ** it in the CCB.
2087 **
2088 ** Returns void
2089 **
2090 *******************************************************************************/
l2cu_process_peer_cfg_rsp(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)2091 void l2cu_process_peer_cfg_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2092 {
2093 /* If we wanted QoS and the peer sends us a positive response with QoS, use his values */
2094 if ( (p_cfg->qos_present) && (p_ccb->our_cfg.qos_present) ) {
2095 p_ccb->our_cfg.qos = p_cfg->qos;
2096 }
2097
2098 if (p_cfg->fcr_present) {
2099 /* Save the retransmission and monitor timeout values */
2100 if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE) {
2101 p_ccb->peer_cfg.fcr.rtrans_tout = p_cfg->fcr.rtrans_tout;
2102 p_ccb->peer_cfg.fcr.mon_tout = p_cfg->fcr.mon_tout;
2103 }
2104
2105 /* Calculate the max number of packets for which we can delay sending an ack */
2106 if (p_cfg->fcr.tx_win_sz < p_ccb->our_cfg.fcr.tx_win_sz) {
2107 p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2108 } else {
2109 p_ccb->fcrb.max_held_acks = p_ccb->our_cfg.fcr.tx_win_sz / 3;
2110 }
2111
2112 L2CAP_TRACE_DEBUG ("l2cu_process_peer_cfg_rsp(): peer tx_win_sz: %d, our tx_win_sz: %d, max_held_acks: %d",
2113 p_cfg->fcr.tx_win_sz, p_ccb->our_cfg.fcr.tx_win_sz, p_ccb->fcrb.max_held_acks);
2114 }
2115 }
2116
2117 /*******************************************************************************
2118 **
2119 ** Function l2cu_process_our_cfg_req
2120 **
2121 ** Description This function is called when we send a "config request"
2122 ** message. It extracts the configuration of interest and saves
2123 ** it in the CCB.
2124 **
2125 ** Returns void
2126 **
2127 *******************************************************************************/
l2cu_process_our_cfg_req(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)2128 void l2cu_process_our_cfg_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2129 {
2130 tL2C_LCB *p_lcb;
2131 UINT16 hci_flush_to;
2132
2133 /* Save the QOS settings we are using for transmit */
2134 if (p_cfg->qos_present) {
2135 p_ccb->our_cfg.qos_present = TRUE;
2136 p_ccb->our_cfg.qos = p_cfg->qos;
2137 }
2138
2139 if (p_cfg->fcr_present) {
2140 /* Override FCR options if attempting streaming or basic */
2141 if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE) {
2142 memset(&p_cfg->fcr, 0, sizeof(tL2CAP_FCR_OPTS));
2143 } else {
2144 /* On BR/EDR, timer values are zero in config request */
2145 /* On class 2 AMP, timer value in config request shall be non-0 processing time */
2146 /* timer value in config response shall be greater than received processing time */
2147 p_cfg->fcr.mon_tout = p_cfg->fcr.rtrans_tout = 0;
2148
2149 if (p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE) {
2150 p_cfg->fcr.max_transmit = p_cfg->fcr.tx_win_sz = 0;
2151 }
2152 }
2153
2154 /* Set the threshold to send acks (may be updated in the cfg response) */
2155 p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2156
2157 /* Include FCS option only if peer can handle it */
2158 if (p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_NO_CRC) {
2159 /* FCS check can be bypassed if peer also desires to bypass */
2160 if (p_cfg->fcs_present && p_cfg->fcs == L2CAP_CFG_FCS_BYPASS) {
2161 p_ccb->bypass_fcs |= L2CAP_CFG_FCS_OUR;
2162 }
2163 } else {
2164 p_cfg->fcs_present = FALSE;
2165 }
2166 } else {
2167 p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
2168 }
2169
2170 p_ccb->our_cfg.fcr.mode = p_cfg->fcr.mode;
2171 p_ccb->our_cfg.fcr_present = p_cfg->fcr_present;
2172
2173 /* Check the flush timeout. If it is lower than the current one used */
2174 /* then we need to adjust the flush timeout sent to the controller */
2175 if (p_cfg->flush_to_present) {
2176 if ((p_cfg->flush_to == 0) || (p_cfg->flush_to == L2CAP_NO_AUTOMATIC_FLUSH)) {
2177 /* don't send invalid flush timeout */
2178 /* SPEC: The sender of the Request shall specify its flush timeout value */
2179 /* if it differs from the default value of 0xFFFF */
2180 p_cfg->flush_to_present = FALSE;
2181 } else {
2182 p_ccb->our_cfg.flush_to = p_cfg->flush_to;
2183 p_lcb = p_ccb->p_lcb;
2184
2185 if (p_cfg->flush_to < p_lcb->link_flush_tout) {
2186 p_lcb->link_flush_tout = p_cfg->flush_to;
2187
2188 /* If the timeout is within range of HCI, set the flush timeout */
2189 if (p_cfg->flush_to <= ((HCI_MAX_AUTO_FLUSH_TOUT * 5) / 8)) {
2190 /* Convert flush timeout to 0.625 ms units, with round */
2191 hci_flush_to = ((p_cfg->flush_to * 8) + 3) / 5;
2192 btsnd_hcic_write_auto_flush_tout (p_lcb->handle, hci_flush_to);
2193 }
2194 }
2195 }
2196 }
2197 }
2198
2199
2200 /*******************************************************************************
2201 **
2202 ** Function l2cu_process_our_cfg_rsp
2203 **
2204 ** Description This function is called when we send the peer a "config response"
2205 ** message. It extracts the configuration of interest and saves
2206 ** it in the CCB.
2207 **
2208 ** Returns void
2209 **
2210 *******************************************************************************/
l2cu_process_our_cfg_rsp(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)2211 void l2cu_process_our_cfg_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2212 {
2213 /* If peer wants QoS, we are allowed to change the values in a positive response */
2214 if ( (p_cfg->qos_present) && (p_ccb->peer_cfg.qos_present) ) {
2215 p_ccb->peer_cfg.qos = p_cfg->qos;
2216 } else {
2217 p_cfg->qos_present = FALSE;
2218 }
2219
2220 l2c_fcr_adj_our_rsp_options (p_ccb, p_cfg);
2221 }
2222 #endif // (L2CAP_COC_INCLUDED == TRUE)
2223
2224
2225 /*******************************************************************************
2226 **
2227 ** Function l2cu_device_reset
2228 **
2229 ** Description This function is called when reset of the device is
2230 ** completed. For all active connection simulate HCI_DISC
2231 **
2232 ** Returns void
2233 **
2234 *******************************************************************************/
l2cu_device_reset(void)2235 void l2cu_device_reset (void)
2236 {
2237 list_node_t *p_node = NULL;
2238 tL2C_LCB *p_lcb = NULL;
2239 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
2240 p_lcb = list_node(p_node);
2241 if ((p_lcb->in_use) && (p_lcb->handle != HCI_INVALID_HANDLE)) {
2242 l2c_link_hci_disc_comp (p_lcb->handle, (UINT8) - 1);
2243 }
2244 }
2245 #if (BLE_INCLUDED == TRUE)
2246 l2cb.is_ble_connecting = FALSE;
2247 #endif
2248 }
2249
2250 /*******************************************************************************
2251 **
2252 ** Function l2cu_create_conn
2253 **
2254 ** Description This function initiates an acl connection via HCI
2255 **
2256 ** Returns TRUE if successful, FALSE if gki get buffer fails.
2257 **
2258 *******************************************************************************/
l2cu_create_conn(tL2C_LCB * p_lcb,tBT_TRANSPORT transport)2259 BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport)
2260 {
2261 #if BTM_SCO_INCLUDED == TRUE
2262 BOOLEAN is_sco_active;
2263 #endif
2264 list_node_t *p_node = NULL;
2265 tL2C_LCB *p_lcb_cur = NULL;
2266
2267 #if (BLE_INCLUDED == TRUE)
2268 tBT_DEVICE_TYPE dev_type;
2269 tBLE_ADDR_TYPE addr_type = p_lcb->open_addr_type;
2270 if(addr_type == BLE_ADDR_UNKNOWN_TYPE) {
2271 BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type);
2272 }
2273
2274 if (transport == BT_TRANSPORT_LE) {
2275 if (!controller_get_interface()->supports_ble()) {
2276 return FALSE;
2277 }
2278 if(addr_type > BLE_ADDR_TYPE_MAX) {
2279 addr_type = BLE_ADDR_PUBLIC;
2280 }
2281 p_lcb->ble_addr_type = addr_type;
2282 p_lcb->transport = BT_TRANSPORT_LE;
2283
2284 return (l2cble_create_conn(p_lcb));
2285 }
2286 #endif
2287
2288 /* If there is a connection where we perform as a slave, try to switch roles
2289 for this connection */
2290 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
2291 p_lcb_cur = list_node(p_node);
2292 if (p_lcb_cur == p_lcb) {
2293 continue;
2294 }
2295
2296 if ((p_lcb_cur->in_use) && (p_lcb_cur->link_role == HCI_ROLE_SLAVE)) {
2297
2298 #if BTM_SCO_INCLUDED == TRUE
2299 /* The LMP_switch_req shall be sent only if the ACL logical transport
2300 is in active mode, when encryption is disabled, and all synchronous
2301 logical transports on the same physical link are disabled." */
2302
2303 /* Check if there is any SCO Active on this BD Address */
2304 is_sco_active = btm_is_sco_active_by_bdaddr(p_lcb_cur->remote_bd_addr);
2305
2306 L2CAP_TRACE_API ("l2cu_create_conn - btm_is_sco_active_by_bdaddr() is_sco_active = %s", \
2307 (is_sco_active == TRUE) ? "TRUE" : "FALSE");
2308
2309 if (is_sco_active == TRUE) {
2310 continue; /* No Master Slave switch not allowed when SCO Active */
2311 }
2312 #endif
2313 /*4_1_TODO check if btm_cb.devcb.local_features to be used instead */
2314 if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures())) {
2315 /* mark this lcb waiting for switch to be completed and
2316 start switch on the other one */
2317 p_lcb->link_state = LST_CONNECTING_WAIT_SWITCH;
2318 p_lcb->link_role = HCI_ROLE_MASTER;
2319
2320 if (BTM_SwitchRole (p_lcb_cur->remote_bd_addr, HCI_ROLE_MASTER, NULL) == BTM_CMD_STARTED) {
2321 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_LINK_ROLE_SWITCH_TOUT);
2322 return (TRUE);
2323 }
2324 }
2325 }
2326 }
2327
2328 p_lcb->link_state = LST_CONNECTING;
2329
2330 return (l2cu_create_conn_after_switch (p_lcb));
2331 }
2332
2333 /*******************************************************************************
2334 **
2335 ** Function l2cu_get_num_hi_priority
2336 **
2337 ** Description Gets the number of high priority channels.
2338 **
2339 ** Returns
2340 **
2341 *******************************************************************************/
l2cu_get_num_hi_priority(void)2342 UINT8 l2cu_get_num_hi_priority (void)
2343 {
2344 UINT8 no_hi = 0;
2345 list_node_t *p_node = NULL;
2346 tL2C_LCB *p_lcb = NULL;
2347
2348 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
2349 p_lcb = list_node(p_node);
2350 if ((p_lcb->in_use) && (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2351 no_hi++;
2352 }
2353 }
2354 return no_hi;
2355 }
2356
2357
2358 /*******************************************************************************
2359 **
2360 ** Function l2cu_create_conn_after_switch
2361 **
2362 ** Description This function initiates an acl connection via HCI
2363 ** If switch required to create connection it is already done.
2364 **
2365 ** Returns TRUE if successful, FALSE if osi get buffer fails.
2366 **
2367 *******************************************************************************/
2368
l2cu_create_conn_after_switch(tL2C_LCB * p_lcb)2369 BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb)
2370 {
2371 UINT8 allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2372 tBTM_INQ_INFO *p_inq_info;
2373 UINT8 page_scan_rep_mode;
2374 UINT8 page_scan_mode;
2375 UINT16 clock_offset;
2376 UINT8 *p_features;
2377 UINT16 num_acl = BTM_GetNumAclLinks();
2378 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_lcb->remote_bd_addr);
2379 UINT8 no_hi_prio_chs = l2cu_get_num_hi_priority();
2380
2381 p_features = BTM_ReadLocalFeatures();
2382
2383 L2CAP_TRACE_DEBUG ("l2cu_create_conn_after_switch :%d num_acl:%d no_hi: %d is_bonding:%d",
2384 l2cb.disallow_switch, num_acl, no_hi_prio_chs, p_lcb->is_bonding);
2385 /* FW team says that we can participant in 4 piconets
2386 * typically 3 piconet + 1 for scanning.
2387 * We can enhance the code to count the number of piconets later. */
2388 if ( ((!l2cb.disallow_switch && (num_acl < 3)) || (p_lcb->is_bonding && (no_hi_prio_chs == 0)))
2389 && HCI_SWITCH_SUPPORTED(p_features)) {
2390 allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2391 } else {
2392 allow_switch = HCI_CR_CONN_NOT_ALLOW_SWITCH;
2393 }
2394
2395 p_lcb->link_state = LST_CONNECTING;
2396
2397 /* Check with the BT manager if details about remote device are known */
2398 if ((p_inq_info = BTM_InqDbRead(p_lcb->remote_bd_addr)) != NULL) {
2399 page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode;
2400 page_scan_mode = p_inq_info->results.page_scan_mode;
2401 clock_offset = (UINT16)(p_inq_info->results.clock_offset);
2402 } else {
2403 /* No info known. Use default settings */
2404 page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R2;
2405 page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;
2406
2407 clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0;
2408 }
2409
2410 if (!btsnd_hcic_create_conn (p_lcb->remote_bd_addr,
2411 ( HCI_PKT_TYPES_MASK_DM1 | HCI_PKT_TYPES_MASK_DH1
2412 | HCI_PKT_TYPES_MASK_DM3 | HCI_PKT_TYPES_MASK_DH3
2413 | HCI_PKT_TYPES_MASK_DM5 | HCI_PKT_TYPES_MASK_DH5 ),
2414 page_scan_rep_mode,
2415 page_scan_mode,
2416 clock_offset,
2417 allow_switch))
2418
2419 {
2420 L2CAP_TRACE_ERROR ("L2CAP - no buffer for l2cu_create_conn");
2421 l2cu_release_lcb (p_lcb);
2422 return (FALSE);
2423 }
2424
2425 btm_acl_update_busy_level (BTM_BLI_PAGE_EVT);
2426
2427 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK,
2428 L2CAP_LINK_CONNECT_TOUT);
2429
2430 return (TRUE);
2431 }
2432
2433
2434 /*******************************************************************************
2435 **
2436 ** Function l2cu_find_lcb_by_state
2437 **
2438 ** Description Look through all active LCBs for a match based on the
2439 ** LCB state.
2440 **
2441 ** Returns pointer to first matched LCB, or NULL if no match
2442 **
2443 *******************************************************************************/
l2cu_find_lcb_by_state(tL2C_LINK_STATE state)2444 tL2C_LCB *l2cu_find_lcb_by_state (tL2C_LINK_STATE state)
2445 {
2446 list_node_t *p_node = NULL;
2447 tL2C_LCB *p_lcb = NULL;
2448
2449 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
2450 p_lcb = list_node(p_node);
2451 if ((p_lcb->in_use) && (p_lcb->link_state == state)) {
2452 return (p_lcb);
2453 }
2454 }
2455
2456 /* If here, no match found */
2457 return (NULL);
2458 }
2459
2460
2461 /*******************************************************************************
2462 **
2463 ** Function l2cu_lcb_disconnecting
2464 **
2465 ** Description On each active lcb, check if the lcb is in disconnecting
2466 ** state, or if there are no ccb's on the lcb (implying
2467 idle timeout is running), or if last ccb on the link
2468 is in disconnecting state.
2469 **
2470 ** Returns TRUE if any of above conditions met, FALSE otherwise
2471 **
2472 *******************************************************************************/
l2cu_lcb_disconnecting(void)2473 BOOLEAN l2cu_lcb_disconnecting (void)
2474 {
2475 tL2C_LCB *p_lcb;
2476 tL2C_CCB *p_ccb;
2477 BOOLEAN status = FALSE;
2478 list_node_t *p_node = NULL;
2479
2480 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
2481 p_lcb = list_node(p_node);
2482 if (p_lcb->in_use) {
2483 /* no ccbs on lcb, or lcb is in disconnecting state */
2484 if ((!p_lcb->ccb_queue.p_first_ccb) || (p_lcb->link_state == LST_DISCONNECTING)) {
2485 status = TRUE;
2486 break;
2487 }
2488 /* only one ccb left on lcb */
2489 else if (p_lcb->ccb_queue.p_first_ccb == p_lcb->ccb_queue.p_last_ccb) {
2490 p_ccb = p_lcb->ccb_queue.p_first_ccb;
2491
2492 if ((p_ccb->in_use) &&
2493 ((p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP) ||
2494 (p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))) {
2495 status = TRUE;
2496 break;
2497 }
2498 }
2499 }
2500 }
2501 return status;
2502 }
2503
2504
2505 /*******************************************************************************
2506 **
2507 ** Function l2cu_set_acl_priority
2508 **
2509 ** Description Sets the transmission priority for a channel.
2510 ** (For initial implementation only two values are valid.
2511 ** L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH).
2512 **
2513 ** Returns TRUE if a valid channel, else FALSE
2514 **
2515 *******************************************************************************/
2516
l2cu_set_acl_priority(BD_ADDR bd_addr,UINT8 priority,BOOLEAN reset_after_rs)2517 BOOLEAN l2cu_set_acl_priority (BD_ADDR bd_addr, UINT8 priority, BOOLEAN reset_after_rs)
2518 {
2519 tL2C_LCB *p_lcb;
2520 UINT8 *pp;
2521 UINT8 command[HCI_BRCM_ACL_PRIORITY_PARAM_SIZE];
2522 UINT8 vs_param;
2523
2524 //APPL_TRACE_EVENT("SET ACL PRIORITY %d", priority);
2525
2526 /* Find the link control block for the acl channel */
2527 if ((p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR)) == NULL) {
2528 L2CAP_TRACE_WARNING ("L2CAP - no LCB for L2CA_SetAclPriority");
2529 return (FALSE);
2530 }
2531
2532 if (BTM_IS_BRCM_CONTROLLER()) {
2533 /* Called from above L2CAP through API; send VSC if changed */
2534 if ((!reset_after_rs && (priority != p_lcb->acl_priority)) ||
2535 /* Called because of a master/slave role switch; if high resend VSC */
2536 ( reset_after_rs && p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2537 pp = command;
2538
2539 vs_param = (priority == L2CAP_PRIORITY_HIGH) ? HCI_BRCM_ACL_PRIORITY_HIGH : HCI_BRCM_ACL_PRIORITY_LOW;
2540
2541 UINT16_TO_STREAM (pp, p_lcb->handle);
2542 UINT8_TO_STREAM (pp, vs_param);
2543
2544 BTM_VendorSpecificCommand (HCI_BRCM_SET_ACL_PRIORITY, HCI_BRCM_ACL_PRIORITY_PARAM_SIZE, command, NULL);
2545
2546 /* Adjust lmp buffer allocation for this channel if priority changed */
2547 if (p_lcb->acl_priority != priority) {
2548 p_lcb->acl_priority = priority;
2549 l2c_link_adjust_allocation();
2550 }
2551 }
2552 }
2553 return (TRUE);
2554 }
2555
2556 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
2557 /******************************************************************************
2558 **
2559 ** Function l2cu_set_non_flushable_pbf
2560 **
2561 ** Description set L2CAP_PKT_START_NON_FLUSHABLE if controller supoorts
2562 **
2563 ** Returns void
2564 **
2565 *******************************************************************************/
l2cu_set_non_flushable_pbf(BOOLEAN is_supported)2566 void l2cu_set_non_flushable_pbf (BOOLEAN is_supported)
2567 {
2568 if (is_supported) {
2569 l2cb.non_flushable_pbf = (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT);
2570 } else {
2571 l2cb.non_flushable_pbf = (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT);
2572 }
2573 }
2574 #endif
2575
2576 /*******************************************************************************
2577 **
2578 ** Function l2cu_resubmit_pending_sec_req
2579 **
2580 ** Description This function is called when required security procedures
2581 ** are completed and any pending requests can be re-submitted.
2582 **
2583 ** Returns void
2584 **
2585 *******************************************************************************/
2586 #if (CLASSIC_BT_INCLUDED == TRUE)
l2cu_resubmit_pending_sec_req(BD_ADDR p_bda)2587 void l2cu_resubmit_pending_sec_req (BD_ADDR p_bda)
2588 {
2589 tL2C_LCB *p_lcb;
2590 tL2C_CCB *p_ccb;
2591 tL2C_CCB *p_next_ccb;
2592 L2CAP_TRACE_DEBUG ("l2cu_resubmit_pending_sec_req p_bda: %p", p_bda);
2593 list_node_t *p_node = NULL;
2594
2595 /* If we are called with a BDA, only resubmit for that BDA */
2596 if (p_bda) {
2597 p_lcb = l2cu_find_lcb_by_bd_addr (p_bda, BT_TRANSPORT_BR_EDR);
2598 /* If we don't have one, this is an error */
2599 if (p_lcb) {
2600 /* For all channels, send the event through their FSMs */
2601 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2602 p_next_ccb = p_ccb->p_next_ccb;
2603 l2c_csm_execute (p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2604 }
2605 } else {
2606 L2CAP_TRACE_WARNING ("l2cu_resubmit_pending_sec_req - unknown BD_ADDR");
2607 }
2608 } else {
2609 /* No BDA pasesed in, so check all links */
2610 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
2611 p_lcb = list_node(p_node);
2612 if (p_lcb->in_use) {
2613 /* For all channels, send the event through their FSMs */
2614 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2615 p_next_ccb = p_ccb->p_next_ccb;
2616 l2c_csm_execute (p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2617 }
2618 }
2619 }
2620 }
2621 }
2622 #endif ///CLASSIC_BT_INCLUDED == TRUE
2623
2624 #if L2CAP_CONFORMANCE_TESTING == TRUE
2625 /*******************************************************************************
2626 **
2627 ** Function l2cu_set_info_rsp_mask
2628 **
2629 ** Description This function allows the script wrapper to change the
2630 ** info resp mask for conformance testing.
2631 **
2632 ** Returns pointer to CCB, or NULL if none
2633 **
2634 *******************************************************************************/
l2cu_set_info_rsp_mask(UINT32 mask)2635 void l2cu_set_info_rsp_mask (UINT32 mask)
2636 {
2637 l2cb.test_info_resp = mask;
2638 }
2639 #endif /* L2CAP_CONFORMANCE_TESTING */
2640
2641 /*******************************************************************************
2642 **
2643 ** Function l2cu_adjust_out_mps
2644 **
2645 ** Description Sets our MPS based on current controller capabilities
2646 **
2647 ** Returns void
2648 **
2649 *******************************************************************************/
l2cu_adjust_out_mps(tL2C_CCB * p_ccb)2650 void l2cu_adjust_out_mps (tL2C_CCB *p_ccb)
2651 {
2652 UINT16 packet_size;
2653
2654 /* on the tx side MTU is selected based on packet size of the controller */
2655 packet_size = btm_get_max_packet_size (p_ccb->p_lcb->remote_bd_addr);
2656
2657 if (packet_size <= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD + L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN)) {
2658 /* something is very wrong */
2659 L2CAP_TRACE_DEBUG ("l2cu_adjust_out_mps bad packet size: %u will use MPS: %u", packet_size, p_ccb->peer_cfg.fcr.mps);
2660 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2661 } else {
2662 packet_size -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD + L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN);
2663
2664 /* We try to negotiate MTU that each packet can be split into whole
2665 number of max packets. For example if link is 1.2 max packet size is 339 bytes.
2666 At first calculate how many whole packets it is. MAX L2CAP is 1691 + 4 overhead.
2667 1695, that will be 5 Dh5 packets. Now maximum L2CAP packet is
2668 5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.
2669
2670 For EDR 2.0 packet size is 1027. So we better send RFCOMM packet as 1 3DH5 packet
2671 1 * 1027 = 1027. Minus 4 bytes L2CAP header 1023. */
2672 if (p_ccb->peer_cfg.fcr.mps >= packet_size) {
2673 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps / packet_size * packet_size;
2674 } else {
2675 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2676 }
2677
2678 L2CAP_TRACE_DEBUG ("l2cu_adjust_out_mps use %d Based on peer_cfg.fcr.mps: %u packet_size: %u",
2679 p_ccb->tx_mps, p_ccb->peer_cfg.fcr.mps, packet_size);
2680 }
2681 }
2682
2683
2684 /*******************************************************************************
2685 **
2686 ** Function l2cu_initialize_fixed_ccb
2687 **
2688 ** Description Initialize a fixed channel's CCB
2689 **
2690 ** Returns TRUE or FALSE
2691 **
2692 *******************************************************************************/
l2cu_initialize_fixed_ccb(tL2C_LCB * p_lcb,UINT16 fixed_cid,tL2CAP_FCR_OPTS * p_fcr)2693 BOOLEAN l2cu_initialize_fixed_ccb (tL2C_LCB *p_lcb, UINT16 fixed_cid, tL2CAP_FCR_OPTS *p_fcr)
2694 {
2695 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2696 tL2C_CCB *p_ccb;
2697 /* If we already have a CCB, then simply return */
2698 if (p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] != NULL) {
2699 return (TRUE);
2700 }
2701
2702 if ((p_ccb = l2cu_allocate_ccb (NULL, 0)) == NULL) {
2703 return (FALSE);
2704 }
2705
2706 btu_stop_timer(&p_lcb->timer_entry);
2707
2708 /* Set CID for the connection */
2709 p_ccb->local_cid = fixed_cid;
2710 p_ccb->remote_cid = fixed_cid;
2711
2712 p_ccb->is_flushable = FALSE;
2713
2714 p_ccb->timer_entry.param = (TIMER_PARAM_TYPE)p_ccb;
2715
2716
2717 if (p_fcr) {
2718 /* Set the FCR parameters. For now, we will use default pools */
2719 p_ccb->our_cfg.fcr = p_ccb->peer_cfg.fcr = *p_fcr;
2720
2721 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
2722 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
2723 p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
2724 p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
2725
2726 p_ccb->fcrb.max_held_acks = p_fcr->tx_win_sz / 3;
2727 }
2728
2729 /* Link ccb to lcb and lcb to ccb */
2730 p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = p_ccb;
2731 p_ccb->p_lcb = p_lcb;
2732
2733 /* There is no configuration, so if the link is up, the channel is up */
2734 if (p_lcb->link_state == LST_CONNECTED) {
2735 p_ccb->chnl_state = CST_OPEN;
2736 }
2737
2738 /* Set the default idle timeout value to use */
2739 p_ccb->fixed_chnl_idle_tout = l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].default_idle_tout;
2740 #endif
2741 return (TRUE);
2742 }
2743
2744 /*******************************************************************************
2745 **
2746 ** Function l2cu_no_dynamic_ccbs
2747 **
2748 ** Description Handles the case when there are no more dynamic CCBs. If there
2749 ** are any fixed CCBs, start the longest of the fixed CCB timeouts,
2750 ** otherwise start the default link idle timeout or disconnect.
2751 **
2752 ** Returns void
2753 **
2754 *******************************************************************************/
l2cu_no_dynamic_ccbs(tL2C_LCB * p_lcb)2755 void l2cu_no_dynamic_ccbs (tL2C_LCB *p_lcb)
2756 {
2757 #if (SMP_INCLUDED == TRUE)
2758 tBTM_STATUS rc;
2759 #endif ///SMP_INCLUDED == TRUE
2760 UINT16 timeout = p_lcb->idle_timeout;
2761
2762 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2763 int xx;
2764
2765 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2766 if ( (p_lcb->p_fixed_ccbs[xx] != NULL) && (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout > timeout) ) {
2767 timeout = p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout;
2768 }
2769 }
2770 #endif
2771
2772 /* If the link is pairing, do not mess with the timeouts */
2773 if (p_lcb->is_bonding) {
2774 return;
2775 }
2776
2777 if (timeout == 0) {
2778 L2CAP_TRACE_DEBUG ("l2cu_no_dynamic_ccbs() IDLE timer 0, disconnecting link");
2779 #if (SMP_INCLUDED == TRUE)
2780 rc = btm_sec_disconnect (p_lcb->handle, HCI_ERR_PEER_USER);
2781 if (rc == BTM_CMD_STARTED) {
2782 l2cu_process_fixed_disc_cback(p_lcb);
2783 p_lcb->link_state = LST_DISCONNECTING;
2784 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2785 } else if (rc == BTM_SUCCESS) {
2786 l2cu_process_fixed_disc_cback(p_lcb);
2787 /* BTM SEC will make sure that link is release (probably after pairing is done) */
2788 p_lcb->link_state = LST_DISCONNECTING;
2789 timeout = 0xFFFF;
2790 } else if ( (p_lcb->is_bonding)
2791 && (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) ) {
2792 l2cu_process_fixed_disc_cback(p_lcb);
2793 p_lcb->link_state = LST_DISCONNECTING;
2794 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2795 } else {
2796 /* probably no buffer to send disconnect */
2797 timeout = BT_1SEC_TIMEOUT;
2798 }
2799 #else
2800 if (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) {
2801 l2cu_process_fixed_disc_cback(p_lcb);
2802 p_lcb->link_state = LST_DISCONNECTING;
2803 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2804 } else {
2805 timeout = BT_1SEC_TIMEOUT;
2806 }
2807 #endif ///SMP_INCLUDED == TRUE
2808
2809 }
2810
2811 if (timeout != 0xFFFF) {
2812 L2CAP_TRACE_DEBUG ("l2cu_no_dynamic_ccbs() starting IDLE timeout: %d", timeout);
2813 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, timeout);
2814 } else {
2815 btu_stop_timer(&p_lcb->timer_entry);
2816 }
2817 }
2818
2819 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2820 /*******************************************************************************
2821 **
2822 ** Function l2cu_process_fixed_chnl_resp
2823 **
2824 ** Description handle a fixed channel response (or lack thereof)
2825 ** if the link failed, or a fixed channel response was
2826 ** not received, the bitfield is all zeros.
2827 **
2828 *******************************************************************************/
l2cu_process_fixed_chnl_resp(tL2C_LCB * p_lcb)2829 void l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb)
2830 {
2831 L2CAP_TRACE_DEBUG("%s",__func__);
2832 #if (BLE_INCLUDED == TRUE)
2833 if (p_lcb->transport == BT_TRANSPORT_BR_EDR) {
2834 /* ignore all not assigned BR/EDR channels */
2835 p_lcb->peer_chnl_mask[0] &= (L2CAP_FIXED_CHNL_SIG_BIT | \
2836 L2CAP_FIXED_CHNL_CNCTLESS_BIT | \
2837 L2CAP_FIXED_CHNL_SMP_BR_BIT);
2838 } else {
2839 p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
2840 }
2841 #endif
2842
2843 /* Tell all registered fixed channels about the connection */
2844 for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2845 #if BLE_INCLUDED == TRUE
2846 /* skip sending LE fix channel callbacks on BR/EDR links */
2847 if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
2848 xx + L2CAP_FIRST_FIXED_CHNL >= L2CAP_ATT_CID &&
2849 xx + L2CAP_FIRST_FIXED_CHNL <= L2CAP_SMP_CID) {
2850 continue;
2851 }
2852 #endif
2853 if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
2854 if (p_lcb->peer_chnl_mask[(xx + L2CAP_FIRST_FIXED_CHNL) / 8]
2855 & (1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8))) {
2856 if (p_lcb->p_fixed_ccbs[xx]) {
2857 p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
2858 }
2859 #if BLE_INCLUDED == TRUE
2860 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2861 p_lcb->remote_bd_addr, TRUE, 0, p_lcb->transport);
2862 #else
2863 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2864 p_lcb->remote_bd_addr, TRUE, 0, BT_TRANSPORT_BR_EDR);
2865 #endif
2866 } else {
2867 #if BLE_INCLUDED == TRUE
2868 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2869 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2870 #else
2871 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2872 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2873 #endif
2874
2875 if (p_lcb->p_fixed_ccbs[xx]) {
2876 l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
2877 p_lcb->p_fixed_ccbs[xx] = NULL;
2878 }
2879 }
2880 }
2881 }
2882 }
2883 #endif
2884
2885
2886 /*******************************************************************************
2887 **
2888 ** Function l2cu_process_fixed_disc_cback
2889 **
2890 ** Description send l2cap fixed channel disconnection callback to application
2891 **
2892 **
2893 ** Returns void
2894 **
2895 *******************************************************************************/
l2cu_process_fixed_disc_cback(tL2C_LCB * p_lcb)2896 void l2cu_process_fixed_disc_cback (tL2C_LCB *p_lcb)
2897 {
2898 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2899
2900 /* Select peer channels mask to use depending on transport */
2901 UINT8 peer_channel_mask = p_lcb->peer_chnl_mask[0];
2902
2903 // For LE, reset the stored peer channel mask
2904 if (p_lcb->transport == BT_TRANSPORT_LE) {
2905 p_lcb->peer_chnl_mask[0] = 0;
2906 }
2907
2908 for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2909 if (p_lcb->p_fixed_ccbs[xx]) {
2910 if (p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb) {
2911 tL2C_CCB *p_l2c_chnl_ctrl_block;
2912 p_l2c_chnl_ctrl_block = p_lcb->p_fixed_ccbs[xx];
2913 p_lcb->p_fixed_ccbs[xx] = NULL;
2914 l2cu_release_ccb(p_l2c_chnl_ctrl_block);
2915 #if BLE_INCLUDED == TRUE
2916 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2917 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2918 #else
2919 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2920 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2921 #endif
2922 }
2923 } else if ( (peer_channel_mask & (1 << (xx + L2CAP_FIRST_FIXED_CHNL)))
2924 && (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) ) {
2925 #if BLE_INCLUDED == TRUE
2926 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2927 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2928 #else
2929 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2930 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2931 #endif
2932 }
2933 }
2934 #endif
2935 }
2936
2937 #if (BLE_INCLUDED == TRUE)
2938 /*******************************************************************************
2939 **
2940 ** Function l2cu_send_peer_ble_par_req
2941 **
2942 ** Description Build and send a BLE parameter update request message
2943 ** to the peer.
2944 **
2945 ** Returns void
2946 **
2947 *******************************************************************************/
l2cu_send_peer_ble_par_req(tL2C_LCB * p_lcb,UINT16 min_int,UINT16 max_int,UINT16 latency,UINT16 timeout)2948 void l2cu_send_peer_ble_par_req (tL2C_LCB *p_lcb, UINT16 min_int, UINT16 max_int,
2949 UINT16 latency, UINT16 timeout)
2950 {
2951 BT_HDR *p_buf;
2952 UINT8 *p;
2953
2954 /* Create an identifier for this packet */
2955 p_lcb->id++;
2956 l2cu_adj_id (p_lcb, L2CAP_ADJ_ID);
2957
2958 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_UPD_REQ_LEN,
2959 L2CAP_CMD_BLE_UPDATE_REQ, p_lcb->id)) == NULL ) {
2960 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_par_req - no buffer");
2961 return;
2962 }
2963
2964 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2965 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2966
2967 UINT16_TO_STREAM (p, min_int);
2968 UINT16_TO_STREAM (p, max_int);
2969 UINT16_TO_STREAM (p, latency);
2970 UINT16_TO_STREAM (p, timeout);
2971
2972 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
2973 }
2974
2975 /*******************************************************************************
2976 **
2977 ** Function l2cu_send_peer_ble_par_rsp
2978 **
2979 ** Description Build and send a BLE parameter update response message
2980 ** to the peer.
2981 **
2982 ** Returns void
2983 **
2984 *******************************************************************************/
l2cu_send_peer_ble_par_rsp(tL2C_LCB * p_lcb,UINT16 reason,UINT8 rem_id)2985 void l2cu_send_peer_ble_par_rsp (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id)
2986 {
2987 BT_HDR *p_buf;
2988 UINT8 *p;
2989
2990 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_UPD_RSP_LEN,
2991 L2CAP_CMD_BLE_UPDATE_RSP, rem_id)) == NULL ) {
2992 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_par_rsp - no buffer");
2993 return;
2994 }
2995
2996 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2997 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2998
2999 UINT16_TO_STREAM (p, reason);
3000
3001 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3002 }
3003
3004 /*******************************************************************************
3005 **
3006 ** Function l2cu_send_peer_ble_credit_based_conn_req
3007 **
3008 ** Description Build and send a BLE packet to establish LE connection oriented
3009 ** L2CAP channel.
3010 **
3011 ** Returns void
3012 **
3013 *******************************************************************************/
l2cu_send_peer_ble_credit_based_conn_req(tL2C_CCB * p_ccb)3014 void l2cu_send_peer_ble_credit_based_conn_req (tL2C_CCB *p_ccb)
3015 {
3016 BT_HDR *p_buf;
3017 UINT8 *p;
3018 tL2C_LCB *p_lcb = NULL;
3019 UINT16 mtu;
3020 UINT16 mps;
3021 UINT16 initial_credit;
3022
3023 if (!p_ccb) {
3024 return;
3025 }
3026 p_lcb = p_ccb->p_lcb;
3027
3028 /* Create an identifier for this packet */
3029 p_ccb->p_lcb->id++;
3030 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3031
3032 p_ccb->local_id = p_ccb->p_lcb->id;
3033
3034 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN,
3035 L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ, p_lcb->id)) == NULL )
3036 {
3037 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
3038 return;
3039 }
3040
3041 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3042 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3043
3044 mtu = p_ccb->local_conn_cfg.mtu;
3045 mps = p_ccb->local_conn_cfg.mps;
3046 initial_credit = p_ccb->local_conn_cfg.credits;
3047
3048 L2CAP_TRACE_DEBUG ("l2cu_send_peer_ble_credit_based_conn_req PSM:0x%04x local_cid:%d\
3049 mtu:%d mps:%d initial_credit:%d", p_ccb->p_rcb->real_psm,\
3050 p_ccb->local_cid, mtu, mps, initial_credit);
3051
3052 UINT16_TO_STREAM (p, p_ccb->p_rcb->real_psm);
3053 UINT16_TO_STREAM (p, p_ccb->local_cid);
3054 UINT16_TO_STREAM (p, mtu);
3055 UINT16_TO_STREAM (p, mps);
3056 UINT16_TO_STREAM (p, initial_credit);
3057
3058 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3059 }
3060
3061 /*******************************************************************************
3062 **
3063 ** Function l2cu_reject_ble_connection
3064 **
3065 ** Description Build and send an L2CAP "Credit based connection res" message
3066 ** to the peer. This function is called for non-success cases.
3067 **
3068 ** Returns void
3069 **
3070 *******************************************************************************/
l2cu_reject_ble_connection(tL2C_LCB * p_lcb,UINT8 rem_id,UINT16 result)3071 void l2cu_reject_ble_connection (tL2C_LCB *p_lcb, UINT8 rem_id, UINT16 result)
3072 {
3073 BT_HDR *p_buf;
3074 UINT8 *p;
3075
3076 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
3077 L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, rem_id)) == NULL )
3078 {
3079 L2CAP_TRACE_WARNING ("l2cu_reject_ble_connection - no buffer");
3080 return;
3081 }
3082
3083 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3084 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3085
3086 UINT16_TO_STREAM (p, 0); /* Local CID of 0 */
3087 UINT16_TO_STREAM (p, 0); /* MTU */
3088 UINT16_TO_STREAM (p, 0); /* MPS */
3089 UINT16_TO_STREAM (p, 0); /* initial credit */
3090 UINT16_TO_STREAM (p, result);
3091
3092 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3093 }
3094
3095 /*******************************************************************************
3096 **
3097 ** Function l2cu_send_peer_ble_credit_based_conn_res
3098 **
3099 ** Description Build and send an L2CAP "Credit based connection res" message
3100 ** to the peer. This function is called in case of success.
3101 **
3102 ** Returns void
3103 **
3104 *******************************************************************************/
l2cu_send_peer_ble_credit_based_conn_res(tL2C_CCB * p_ccb,UINT16 result)3105 void l2cu_send_peer_ble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result)
3106 {
3107 BT_HDR *p_buf;
3108 UINT8 *p;
3109
3110 L2CAP_TRACE_DEBUG ("l2cu_send_peer_ble_credit_based_conn_res");
3111 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
3112 L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, p_ccb->remote_id)) == NULL )
3113 {
3114 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_res - no buffer");
3115 return;
3116 }
3117
3118 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3119 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3120
3121 UINT16_TO_STREAM (p, p_ccb->local_cid); /* Local CID */
3122 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.mtu); /* MTU */
3123 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.mps); /* MPS */
3124 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.credits); /* initial credit */
3125 UINT16_TO_STREAM (p, result);
3126
3127 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
3128 }
3129
3130 /*******************************************************************************
3131 **
3132 ** Function l2cu_send_peer_ble_flow_control_credit
3133 **
3134 ** Description Build and send a BLE packet to give credits to peer device
3135 ** for LE connection oriented L2CAP channel.
3136 **
3137 ** Returns void
3138 **
3139 *******************************************************************************/
l2cu_send_peer_ble_flow_control_credit(tL2C_CCB * p_ccb,UINT16 credit_value)3140 void l2cu_send_peer_ble_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value)
3141 {
3142 BT_HDR *p_buf;
3143 UINT8 *p;
3144 tL2C_LCB *p_lcb = NULL;
3145
3146 if (!p_ccb) {
3147 return;
3148 }
3149 p_lcb = p_ccb->p_lcb;
3150
3151 /* Create an identifier for this packet */
3152 p_ccb->p_lcb->id++;
3153 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3154
3155 p_ccb->local_id = p_ccb->p_lcb->id;
3156
3157 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN,
3158 L2CAP_CMD_BLE_FLOW_CTRL_CREDIT, p_lcb->id)) == NULL )
3159 {
3160 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
3161 return;
3162 }
3163
3164 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3165 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3166
3167 UINT16_TO_STREAM (p, p_ccb->local_cid);
3168 UINT16_TO_STREAM (p, credit_value);
3169
3170 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3171 }
3172
3173 /*******************************************************************************
3174 **
3175 ** Function l2cu_send_peer_ble_credit_based_conn_req
3176 **
3177 ** Description Build and send a BLE packet to disconnect LE connection oriented
3178 ** L2CAP channel.
3179 **
3180 ** Returns void
3181 **
3182 *******************************************************************************/
l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB * p_ccb)3183 void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB *p_ccb)
3184 {
3185 BT_HDR *p_buf;
3186 UINT8 *p;
3187 tL2C_LCB *p_lcb = NULL;
3188 L2CAP_TRACE_DEBUG ("%s",__func__);
3189
3190 if (!p_ccb) {
3191 return;
3192 }
3193 p_lcb = p_ccb->p_lcb;
3194
3195 /* Create an identifier for this packet */
3196 p_ccb->p_lcb->id++;
3197 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3198
3199 p_ccb->local_id = p_ccb->p_lcb->id;
3200 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_DISC_REQ_LEN,
3201 L2CAP_CMD_DISC_REQ, p_lcb->id)) == NULL )
3202 {
3203 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_disconn_req - no buffer");
3204 return;
3205 }
3206
3207 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3208 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3209
3210 UINT16_TO_STREAM (p, p_ccb->remote_cid);
3211 UINT16_TO_STREAM (p,p_ccb->local_cid);
3212
3213 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3214 }
3215
3216 #endif /* BLE_INCLUDED == TRUE */
3217
3218 /*******************************************************************************
3219 ** Functions used by both Full and Light Stack
3220 ********************************************************************************/
3221
3222 /*******************************************************************************
3223 **
3224 ** Function l2cu_find_lcb_by_handle
3225 **
3226 ** Description Look through all active LCBs for a match based on the
3227 ** HCI handle.
3228 **
3229 ** Returns pointer to matched LCB, or NULL if no match
3230 **
3231 *******************************************************************************/
l2cu_find_lcb_by_handle(UINT16 handle)3232 tL2C_LCB *l2cu_find_lcb_by_handle (UINT16 handle)
3233 {
3234 list_node_t *p_node = NULL;
3235 tL2C_LCB *p_lcb = NULL;
3236 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
3237 p_lcb = list_node(p_node);
3238 if ((p_lcb->in_use) && (p_lcb->handle == handle)) {
3239 return (p_lcb);
3240 }
3241 }
3242
3243 /* If here, no match found */
3244 return (NULL);
3245 }
3246
3247 /*******************************************************************************
3248 **
3249 ** Function l2cu_find_ccb_by_cid
3250 **
3251 ** Description Look through all active CCBs on a link for a match based
3252 ** on the local CID. If passed the link pointer is NULL, all
3253 ** active links are searched.
3254 **
3255 ** Returns pointer to matched CCB, or NULL if no match
3256 **
3257 *******************************************************************************/
l2cu_find_ccb_in_list(void * p_ccb_node,void * p_local_cid)3258 bool l2cu_find_ccb_in_list(void *p_ccb_node, void *p_local_cid)
3259 {
3260 tL2C_CCB *p_ccb = (tL2C_CCB *)p_ccb_node;
3261 uint8_t local_cid = *((uint8_t *)p_local_cid);
3262
3263 if (p_ccb->local_cid == local_cid && p_ccb->in_use) {
3264 return FALSE;
3265 }
3266 return TRUE;
3267 }
3268
l2cu_find_ccb_by_cid(tL2C_LCB * p_lcb,UINT16 local_cid)3269 tL2C_CCB *l2cu_find_ccb_by_cid (tL2C_LCB *p_lcb, UINT16 local_cid)
3270 {
3271 tL2C_CCB *p_ccb = NULL;
3272 #if (L2CAP_UCD_INCLUDED == FALSE)
3273 if (local_cid < L2CAP_BASE_APPL_CID) {
3274 return NULL;
3275 }
3276 #endif //(L2CAP_UCD_INCLUDED == FALSE)
3277 list_node_t *p_node = NULL;
3278
3279 p_node = (list_foreach(l2cb.p_ccb_pool, l2cu_find_ccb_in_list, &local_cid));
3280 if (p_node) {
3281 p_ccb = (tL2C_CCB *)list_node(p_node);
3282
3283 if (p_lcb && p_lcb != p_ccb->p_lcb) {
3284 p_ccb = NULL;
3285 }
3286 }
3287
3288 return (p_ccb);
3289 }
3290
l2cu_find_free_ccb(void)3291 tL2C_CCB *l2cu_find_free_ccb (void)
3292 {
3293 tL2C_CCB *p_ccb = NULL;
3294
3295 list_node_t *p_node = NULL;
3296
3297 for (p_node = list_begin(l2cb.p_ccb_pool); p_node; p_node = list_next(p_node))
3298 {
3299 p_ccb = list_node(p_node);
3300 if(p_ccb && !p_ccb->in_use ) {
3301 return p_ccb;
3302 }
3303 }
3304
3305 return (NULL);
3306 }
3307
3308 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE && CLASSIC_BT_INCLUDED == TRUE)
3309
3310 /******************************************************************************
3311 **
3312 ** Function l2cu_get_next_channel_in_rr
3313 **
3314 ** Description get the next channel to send on a link. It also adjusts the
3315 ** CCB queue to do a basic priority and round-robin scheduling.
3316 **
3317 ** Returns pointer to CCB or NULL
3318 **
3319 *******************************************************************************/
l2cu_get_next_channel_in_rr(tL2C_LCB * p_lcb)3320 static tL2C_CCB *l2cu_get_next_channel_in_rr(tL2C_LCB *p_lcb)
3321 {
3322 tL2C_CCB *p_serve_ccb = NULL;
3323 tL2C_CCB *p_ccb;
3324
3325 int i, j;
3326
3327 /* scan all of priority until finding a channel to serve */
3328 for ( i = 0; (i < L2CAP_NUM_CHNL_PRIORITY) && (!p_serve_ccb); i++ ) {
3329 /* scan all channel within serving priority group until finding a channel to serve */
3330 for ( j = 0; (j < p_lcb->rr_serv[p_lcb->rr_pri].num_ccb) && (!p_serve_ccb); j++) {
3331 /* scaning from next serving channel */
3332 p_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb;
3333
3334 if (!p_ccb) {
3335 L2CAP_TRACE_ERROR("p_serve_ccb is NULL, rr_pri=%d", p_lcb->rr_pri);
3336 return NULL;
3337 }
3338
3339 L2CAP_TRACE_DEBUG("RR scan pri=%d, lcid=0x%04x, q_cout=%d",
3340 p_ccb->ccb_priority, p_ccb->local_cid,
3341 fixed_queue_length(p_ccb->xmit_hold_q));
3342
3343 /* store the next serving channel */
3344 /* this channel is the last channel of its priority group */
3345 if (( p_ccb->p_next_ccb == NULL )
3346 || ( p_ccb->p_next_ccb->ccb_priority != p_ccb->ccb_priority )) {
3347 /* next serving channel is set to the first channel in the group */
3348 p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_first_ccb;
3349 } else {
3350 /* next serving channel is set to the next channel in the group */
3351 p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_ccb->p_next_ccb;
3352 }
3353
3354 if (p_ccb->chnl_state != CST_OPEN) {
3355 continue;
3356 }
3357
3358 /* eL2CAP option in use */
3359 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3360 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3361 continue;
3362 }
3363
3364 if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3365 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3366 continue;
3367 }
3368
3369
3370 #if (CLASSIC_BT_INCLUDED == TRUE)
3371 /* If in eRTM mode, check for window closure */
3372 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3373 continue;
3374 }
3375 #endif ///CLASSIC_BT_INCLUDED == TRUE
3376 }
3377 } else {
3378 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3379 continue;
3380 }
3381 }
3382
3383 /* found a channel to serve */
3384 p_serve_ccb = p_ccb;
3385 /* decrease quota of its priority group */
3386 p_lcb->rr_serv[p_lcb->rr_pri].quota--;
3387 }
3388
3389 /* if there is no more quota of the priority group or no channel to have data to send */
3390 if ((p_lcb->rr_serv[p_lcb->rr_pri].quota == 0) || (!p_serve_ccb)) {
3391 /* serve next priority group */
3392 p_lcb->rr_pri = (p_lcb->rr_pri + 1) % L2CAP_NUM_CHNL_PRIORITY;
3393 /* initialize its quota */
3394 p_lcb->rr_serv[p_lcb->rr_pri].quota = L2CAP_GET_PRIORITY_QUOTA(p_lcb->rr_pri);
3395 }
3396 }
3397
3398 if (p_serve_ccb) {
3399 L2CAP_TRACE_DEBUG("RR service pri=%d, quota=%d, lcid=0x%04x",
3400 p_serve_ccb->ccb_priority,
3401 p_lcb->rr_serv[p_serve_ccb->ccb_priority].quota,
3402 p_serve_ccb->local_cid );
3403 }
3404
3405 return p_serve_ccb;
3406 }
3407
3408 #else /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
3409
3410 /******************************************************************************
3411 **
3412 ** Function l2cu_get_next_channel
3413 **
3414 ** Description get the next channel to send on a link bassed on priority
3415 ** scheduling.
3416 **
3417 ** Returns pointer to CCB or NULL
3418 **
3419 *******************************************************************************/
3420 #if (CLASSIC_BT_INCLUDED == TRUE)
l2cu_get_next_channel(tL2C_LCB * p_lcb)3421 static tL2C_CCB *l2cu_get_next_channel(tL2C_LCB *p_lcb)
3422 {
3423 tL2C_CCB *p_ccb;
3424
3425 /* Get the first CCB with data to send.
3426 */
3427 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) {
3428 if (p_ccb->chnl_state != CST_OPEN) {
3429 continue;
3430 }
3431
3432 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3433 continue;
3434 }
3435
3436 if (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q))
3437 return p_ccb;
3438 }
3439
3440 if (fixed_queue_is_empty(p_ccb->xmit_hold_q))
3441 continue;
3442 }
3443
3444 /* If in eRTM mode, check for window closure */
3445 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3446 continue;
3447 }
3448
3449 /* If here, we found someone */
3450 return p_ccb;
3451 }
3452
3453 return NULL;
3454 }
3455 #endif ///CLASSIC_BT_INCLUDED == TRUE
3456
3457 #endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
3458
3459 /******************************************************************************
3460 **
3461 ** Function l2cu_get_next_buffer_to_send
3462 **
3463 ** Description get the next buffer to send on a link. It also adjusts the
3464 ** CCB queue to do a basic priority and round-robin scheduling.
3465 **
3466 ** Returns pointer to buffer or NULL
3467 **
3468 *******************************************************************************/
3469 BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
3470 {
3471 tL2C_CCB *p_ccb;
3472 BT_HDR *p_buf = NULL;
3473
3474 /* Highest priority are fixed channels */
3475 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3476 int xx;
3477
3478 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3479 if ((p_ccb = p_lcb->p_fixed_ccbs[xx]) == NULL) {
3480 continue;
3481 }
3482
3483 /* eL2CAP option in use */
3484 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3485 #if (CLASSIC_BT_INCLUDED == TRUE)
3486 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3487 continue;
3488 }
3489
3490 /* No more checks needed if sending from the reatransmit queue */
3491 if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q))
3492 {
3493 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3494 continue;
3495 }
3496 /* If in eRTM mode, check for window closure */
3497 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3498 continue;
3499 }
3500 }
3501 if ((p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0)) != NULL) {
3502 l2cu_check_channel_congestion (p_ccb);
3503 l2cu_set_acl_hci_header (p_buf, p_ccb);
3504 return (p_buf);
3505 }
3506 #else
3507 continue;
3508 #endif ///CLASSIC_BT_INCLUDED == TRUE
3509
3510 } else {
3511 if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3512 p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->xmit_hold_q, 0);
3513 if (NULL == p_buf) {
3514 L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send: No data to be sent");
3515 return (NULL);
3516 }
3517 l2cu_check_channel_congestion (p_ccb);
3518 l2cu_set_acl_hci_header (p_buf, p_ccb);
3519 /* send tx complete */
3520 if (l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb) {
3521 (*l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)(p_ccb->local_cid, 1);
3522 }
3523 return (p_buf);
3524 }
3525 }
3526 }
3527 #endif
3528 #if (CLASSIC_BT_INCLUDED == TRUE)
3529 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
3530 /* get next serving channel in round-robin */
3531 p_ccb = l2cu_get_next_channel_in_rr( p_lcb );
3532 #else
3533 p_ccb = l2cu_get_next_channel( p_lcb );
3534 #endif
3535
3536 /* Return if no buffer */
3537 if (p_ccb == NULL) {
3538 return (NULL);
3539 }
3540
3541 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3542
3543 if ((p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0)) == NULL) {
3544 return (NULL);
3545 }
3546
3547 } else {
3548 p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->xmit_hold_q, 0);
3549 if (NULL == p_buf) {
3550 L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send() #2: No data to be sent");
3551 return (NULL);
3552 }
3553 }
3554
3555 if ( p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb && (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE) ) {
3556 (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1);
3557 }
3558
3559
3560 l2cu_check_channel_congestion (p_ccb);
3561
3562 l2cu_set_acl_hci_header (p_buf, p_ccb);
3563 #endif ///CLASSIC_BT_INCLUDED == TRUE
3564
3565 return (p_buf);
3566 }
3567
3568 /******************************************************************************
3569 **
3570 ** Function l2cu_set_acl_hci_header
3571 **
3572 ** Description Set HCI handle for ACL packet
3573 **
3574 ** Returns None
3575 **
3576 *******************************************************************************/
3577 void l2cu_set_acl_hci_header (BT_HDR *p_buf, tL2C_CCB *p_ccb)
3578 {
3579 UINT8 *p;
3580
3581 /* Set the pointer to the beginning of the data minus 4 bytes for the packet header */
3582 p = (UINT8 *)(p_buf + 1) + p_buf->offset - HCI_DATA_PREAMBLE_SIZE;
3583
3584 #if (BLE_INCLUDED == TRUE)
3585 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3586 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT));
3587
3588 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_ble();
3589 /* The HCI transport will segment the buffers. */
3590 if (p_buf->len > acl_data_size) {
3591 UINT16_TO_STREAM (p, acl_data_size);
3592 } else {
3593 UINT16_TO_STREAM (p, p_buf->len);
3594 }
3595 } /* (BLE_INCLUDED == TRUE) */
3596 else
3597 #endif
3598 {
3599 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
3600 if ( (((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) == L2CAP_FLUSHABLE_CH_BASED) && (p_ccb->is_flushable))
3601 || ((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) == L2CAP_FLUSHABLE_PKT) ) {
3602 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3603 } else {
3604 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | l2cb.non_flushable_pbf);
3605 }
3606 #else
3607 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3608 #endif
3609
3610 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic();
3611 /* The HCI transport will segment the buffers. */
3612 if (p_buf->len > acl_data_size) {
3613 UINT16_TO_STREAM (p, acl_data_size);
3614 } else {
3615 UINT16_TO_STREAM (p, p_buf->len);
3616 }
3617 }
3618 p_buf->offset -= HCI_DATA_PREAMBLE_SIZE;
3619 p_buf->len += HCI_DATA_PREAMBLE_SIZE;
3620 }
3621
3622 /******************************************************************************
3623 **
3624 ** Function l2cu_check_channel_congestion
3625 **
3626 ** Description check if any change in congestion status
3627 **
3628 ** Returns None
3629 **
3630 *******************************************************************************/
3631 void l2cu_check_channel_congestion (tL2C_CCB *p_ccb)
3632 {
3633 size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q);
3634 #if (CLASSIC_BT_INCLUDED == TRUE)
3635 size_t q_waiting_ack_count = fixed_queue_length(p_ccb->fcrb.waiting_for_ack_q);
3636 #endif
3637
3638 #if (L2CAP_UCD_INCLUDED == TRUE)
3639 if ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3640 q_count += fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q);
3641 }
3642 #endif
3643 /* If the CCB queue limit is subject to a quota, check for congestion */
3644 /* if this channel has outgoing traffic */
3645 if (p_ccb->buff_quota != 0) {
3646 /* If this channel was congested */
3647 if ( p_ccb->cong_sent ) {
3648 /* If the channel is not congested now, tell the app */
3649 if (q_count <= (p_ccb->buff_quota / 2)
3650 #if (CLASSIC_BT_INCLUDED == TRUE)
3651 && (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE || q_waiting_ack_count < p_ccb->our_cfg.fcr.tx_win_sz)
3652 #endif
3653 ) {
3654 p_ccb->cong_sent = FALSE;
3655 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3656 L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (FALSE), CID: 0x%04x xmit_hold_q.count: %u buff_quota: %u",
3657 p_ccb->local_cid, q_count, p_ccb->buff_quota);
3658
3659 /* Prevent recursive calling */
3660 l2cb.is_cong_cback_context = TRUE;
3661 (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, FALSE);
3662 l2cb.is_cong_cback_context = FALSE;
3663 }
3664 #if (L2CAP_UCD_INCLUDED == TRUE)
3665 else if ( p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3666 if ( p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ) {
3667 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCD CongestionStatus_Cb (FALSE), SecPendingQ:%u,XmitQ:%u,Quota:%u",
3668 fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3669 fixed_queue_length(p_ccb->xmit_hold_q),
3670 p_ccb->buff_quota);
3671 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( p_ccb->p_lcb->remote_bd_addr, FALSE );
3672 }
3673 }
3674 #endif
3675 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3676 else {
3677 UINT8 xx;
3678 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx ++) {
3679 if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3680 if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL) {
3681 (* l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr, FALSE);
3682 }
3683 break;
3684 }
3685 }
3686 }
3687 #endif
3688 }
3689 } else {
3690 tL2C_LCB *p_lcb = p_ccb->p_lcb;
3691 /* If this channel was not congested but it is congested now, tell the app */
3692 if (q_count > p_ccb->buff_quota || (p_lcb && (p_lcb->link_xmit_data_q) && (list_length(p_lcb->link_xmit_data_q) + q_count) > p_ccb->buff_quota)
3693 #if (CLASSIC_BT_INCLUDED == TRUE)
3694 || (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE && q_waiting_ack_count >= p_ccb->our_cfg.fcr.tx_win_sz)
3695 #endif
3696 ) {
3697 p_ccb->cong_sent = TRUE;
3698 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3699 L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (TRUE),CID:0x%04x,XmitQ:%u,Quota:%u",
3700 p_ccb->local_cid, q_count, p_ccb->buff_quota);
3701
3702 (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, TRUE);
3703 }
3704 #if (L2CAP_UCD_INCLUDED == TRUE)
3705 else if ( p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3706 if ( p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ) {
3707 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCD CongestionStatus_Cb (TRUE), SecPendingQ:%u,XmitQ:%u,Quota:%u",
3708 fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3709 fixed_queue_length(p_ccb->xmit_hold_q),
3710 p_ccb->buff_quota);
3711 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( p_ccb->p_lcb->remote_bd_addr, TRUE );
3712 }
3713 }
3714 #endif
3715 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3716 else {
3717 UINT8 xx;
3718 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx ++) {
3719 if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3720 if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL) {
3721 (* l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr, TRUE);
3722 }
3723 break;
3724 }
3725 }
3726 }
3727 #endif
3728 }
3729 }
3730 }
3731 }
3732