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