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; /* Default mode for channel is basic mode */
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 (SDP_INCLUDED == TRUE)
1680 if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) {
1681 btm_sec_clr_service_by_psm(p_rcb->psm);
1682 }
1683 #endif ///SMP_INCLUDED == TRUE
1684 if (p_ccb->should_free_rcb) {
1685 osi_free(p_rcb);
1686 p_ccb->p_rcb = NULL;
1687 p_ccb->should_free_rcb = false;
1688 }
1689 if (p_lcb) {
1690 btm_sec_clr_temp_auth_service (p_lcb->remote_bd_addr);
1691 }
1692
1693 /* Stop and free the timer */
1694 btu_free_timer (&p_ccb->timer_entry);
1695
1696 fixed_queue_free(p_ccb->xmit_hold_q, osi_free_func);
1697 p_ccb->xmit_hold_q = NULL;
1698 #if (CLASSIC_BT_INCLUDED == TRUE)
1699 fixed_queue_free(p_ccb->fcrb.srej_rcv_hold_q, osi_free_func);
1700 fixed_queue_free(p_ccb->fcrb.retrans_q, osi_free_func);
1701 fixed_queue_free(p_ccb->fcrb.waiting_for_ack_q, osi_free_func);
1702 p_ccb->fcrb.srej_rcv_hold_q = NULL;
1703 p_ccb->fcrb.retrans_q = NULL;
1704 p_ccb->fcrb.waiting_for_ack_q = NULL;
1705 #endif ///CLASSIC_BT_INCLUDED == TRUE
1706
1707
1708 #if (CLASSIC_BT_INCLUDED == TRUE)
1709 l2c_fcr_cleanup (p_ccb);
1710 #endif ///CLASSIC_BT_INCLUDED == TRUE
1711 /* Channel may not be assigned to any LCB if it was just pre-reserved */
1712 if ( (p_lcb) &&
1713 ( (p_ccb->local_cid >= L2CAP_BASE_APPL_CID)
1714 #if (L2CAP_UCD_INCLUDED == TRUE)
1715 || (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID)
1716 #endif
1717 )
1718 ) {
1719 l2cu_dequeue_ccb (p_ccb);
1720
1721 /* Delink the CCB from the LCB */
1722 p_ccb->p_lcb = NULL;
1723 }
1724
1725
1726 /* Flag as not in use */
1727 p_ccb->in_use = FALSE;
1728
1729 /* If no channels on the connection, start idle timeout */
1730 if ((p_lcb) && p_lcb->in_use && (p_lcb->link_state == LST_CONNECTED)) {
1731 if (!p_lcb->ccb_queue.p_first_ccb) {
1732 l2cu_no_dynamic_ccbs (p_lcb);
1733 } else {
1734 /* Link is still active, adjust channel quotas. */
1735 l2c_link_adjust_chnl_allocation ();
1736 }
1737 }
1738 }
1739
1740 /*******************************************************************************
1741 **
1742 ** Function l2cu_find_ccb_by_remote_cid
1743 **
1744 ** Description Look through all active CCBs on a link for a match based
1745 ** on the remote CID.
1746 **
1747 ** Returns pointer to matched CCB, or NULL if no match
1748 **
1749 *******************************************************************************/
l2cu_find_ccb_by_remote_cid(tL2C_LCB * p_lcb,UINT16 remote_cid)1750 tL2C_CCB *l2cu_find_ccb_by_remote_cid (tL2C_LCB *p_lcb, UINT16 remote_cid)
1751 {
1752 tL2C_CCB *p_ccb;
1753
1754 /* If LCB is NULL, look through all active links */
1755 if (!p_lcb) {
1756 return NULL;
1757 } else {
1758 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
1759 if ((p_ccb->in_use) && (p_ccb->remote_cid == remote_cid)) {
1760 return (p_ccb);
1761 }
1762 }
1763
1764 /* If here, no match found */
1765 return (NULL);
1766 }
1767
1768 /*******************************************************************************
1769 **
1770 ** Function l2cu_allocate_rcb
1771 **
1772 ** Description Look through the Registration Control Blocks for a free
1773 ** one.
1774 **
1775 ** Returns Pointer to the RCB or NULL if not found
1776 **
1777 *******************************************************************************/
l2cu_allocate_rcb(UINT16 psm)1778 tL2C_RCB *l2cu_allocate_rcb (UINT16 psm)
1779 {
1780 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
1781 UINT16 xx;
1782
1783 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1784 if (!p_rcb->in_use) {
1785 p_rcb->in_use = TRUE;
1786 p_rcb->psm = psm;
1787 #if (L2CAP_UCD_INCLUDED == TRUE)
1788 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
1789 #endif
1790 return (p_rcb);
1791 }
1792 }
1793
1794 /* If here, no free RCB found */
1795 return (NULL);
1796 }
1797
1798 #if (BLE_INCLUDED == TRUE)
1799 /*******************************************************************************
1800 **
1801 ** Function l2cu_allocate_ble_rcb
1802 **
1803 ** Description Look through the BLE Registration Control Blocks for a free
1804 ** one.
1805 **
1806 ** Returns Pointer to the BLE RCB or NULL if not found
1807 **
1808 *******************************************************************************/
l2cu_allocate_ble_rcb(UINT16 psm)1809 tL2C_RCB *l2cu_allocate_ble_rcb (UINT16 psm)
1810 {
1811 tL2C_RCB *p_rcb = &l2cb.ble_rcb_pool[0];
1812 UINT16 xx;
1813
1814 for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++)
1815 {
1816 if (!p_rcb->in_use)
1817 {
1818 p_rcb->in_use = TRUE;
1819 p_rcb->psm = psm;
1820 #if (L2CAP_UCD_INCLUDED == TRUE)
1821 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
1822 #endif
1823 return (p_rcb);
1824 }
1825 }
1826
1827 /* If here, no free RCB found */
1828 return (NULL);
1829 }
1830 #endif ///BLE_INCLUDED == TRUE
1831
1832 /*******************************************************************************
1833 **
1834 ** Function l2cu_release_rcb
1835 **
1836 ** Description Mark an RCB as no longet in use
1837 **
1838 ** Returns void
1839 **
1840 *******************************************************************************/
l2cu_release_rcb(tL2C_RCB * p_rcb)1841 void l2cu_release_rcb (tL2C_RCB *p_rcb)
1842 {
1843 p_rcb->in_use = FALSE;
1844 p_rcb->psm = 0;
1845 }
1846
1847
1848 /*******************************************************************************
1849 **
1850 ** Function l2cu_disconnect_chnl
1851 **
1852 ** Description Disconnect a channel. Typically, this is due to either
1853 ** receiving a bad configuration, bad packet or max_retries expiring.
1854 **
1855 *******************************************************************************/
l2cu_disconnect_chnl(tL2C_CCB * p_ccb)1856 void l2cu_disconnect_chnl (tL2C_CCB *p_ccb)
1857 {
1858 UINT16 local_cid = p_ccb->local_cid;
1859
1860 if (local_cid >= L2CAP_BASE_APPL_CID) {
1861 tL2CA_DISCONNECT_IND_CB *p_disc_cb = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
1862
1863 L2CAP_TRACE_WARNING ("L2CAP - disconnect_chnl CID: 0x%04x", local_cid);
1864
1865 l2cu_send_peer_disc_req (p_ccb);
1866
1867 l2cu_release_ccb (p_ccb);
1868
1869 (*p_disc_cb)(local_cid, FALSE);
1870 } else {
1871 /* failure on the AMP channel, probably need to disconnect ACL */
1872 L2CAP_TRACE_ERROR ("L2CAP - disconnect_chnl CID: 0x%04x Ignored", local_cid);
1873 }
1874 }
1875
1876
1877 /*******************************************************************************
1878 **
1879 ** Function l2cu_find_rcb_by_psm
1880 **
1881 ** Description Look through the Registration Control Blocks to see if
1882 ** anyone registered to handle the PSM in question
1883 **
1884 ** Returns Pointer to the RCB or NULL if not found
1885 **
1886 *******************************************************************************/
l2cu_find_rcb_by_psm(UINT16 psm)1887 tL2C_RCB *l2cu_find_rcb_by_psm (UINT16 psm)
1888 {
1889 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
1890 UINT16 xx;
1891
1892 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1893 if ((p_rcb->in_use) && (p_rcb->psm == psm)) {
1894 return (p_rcb);
1895 }
1896 }
1897
1898 /* If here, no match found */
1899 return (NULL);
1900 }
1901
1902 #if (BLE_INCLUDED == TRUE)
1903 /*******************************************************************************
1904 **
1905 ** Function l2cu_find_ble_rcb_by_psm
1906 **
1907 ** Description Look through the BLE Registration Control Blocks to see if
1908 ** anyone registered to handle the PSM in question
1909 **
1910 ** Returns Pointer to the BLE RCB or NULL if not found
1911 **
1912 *******************************************************************************/
l2cu_find_ble_rcb_by_psm(UINT16 psm)1913 tL2C_RCB *l2cu_find_ble_rcb_by_psm (UINT16 psm)
1914 {
1915 tL2C_RCB *p_rcb = &l2cb.ble_rcb_pool[0];
1916 UINT16 xx;
1917
1918 for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++)
1919 {
1920 if ((p_rcb->in_use) && (p_rcb->psm == psm)) {
1921 return (p_rcb);
1922 }
1923 }
1924
1925 /* If here, no match found */
1926 return (NULL);
1927 }
1928 #endif ///BLE_INCLUDED == TRUE
1929
1930
1931 /*******************************************************************************
1932 **
1933 ** Function l2cu_process_peer_cfg_req
1934 **
1935 ** Description This function is called when the peer sends us a "config request"
1936 ** message. It extracts the configuration of interest and saves
1937 ** it in the CCB.
1938 **
1939 ** Note: Negotiation of the FCR channel type is handled internally,
1940 ** all others are passed to the upper layer.
1941 **
1942 ** Returns UINT8 - L2CAP_PEER_CFG_OK if passed to upper layer,
1943 ** L2CAP_PEER_CFG_UNACCEPTABLE if automatically responded to
1944 ** because parameters are unnacceptable from a specification
1945 ** point of view.
1946 ** L2CAP_PEER_CFG_DISCONNECT if no compatible channel modes
1947 ** between the two devices, and shall be closed.
1948 **
1949 *******************************************************************************/
l2cu_process_peer_cfg_req(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)1950 UINT8 l2cu_process_peer_cfg_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
1951 {
1952 BOOLEAN mtu_ok = TRUE;
1953 BOOLEAN qos_type_ok = TRUE;
1954 BOOLEAN flush_to_ok = TRUE;
1955 BOOLEAN fcr_ok = TRUE;
1956 #if (CLASSIC_BT_INCLUDED == TRUE)
1957 UINT8 fcr_status;
1958 #endif ///CLASSIC_BT_INCLUDED == TRUE
1959 /* Ignore FCR parameters for basic mode */
1960 if (!p_cfg->fcr_present) {
1961 p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
1962 }
1963
1964 /* Save the MTU that our peer can receive */
1965 if (p_cfg->mtu_present) {
1966 /* Make sure MTU is at least the minimum */
1967 if (p_cfg->mtu >= L2CAP_MIN_MTU) {
1968 /* In basic mode, limit the MTU to our buffer size */
1969 if ( (p_cfg->fcr_present == FALSE) && (p_cfg->mtu > L2CAP_MTU_SIZE) ) {
1970 p_cfg->mtu = L2CAP_MTU_SIZE;
1971 }
1972
1973 /* Save the accepted value in case of renegotiation */
1974 p_ccb->peer_cfg.mtu = p_cfg->mtu;
1975 p_ccb->peer_cfg.mtu_present = TRUE;
1976 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_MTU;
1977 } else { /* Illegal MTU value */
1978 p_cfg->mtu = L2CAP_MIN_MTU;
1979 mtu_ok = FALSE;
1980 }
1981 }
1982 /* Reload mtu from a previously accepted config request */
1983 else if (p_ccb->peer_cfg.mtu_present) {
1984 p_cfg->mtu_present = TRUE;
1985 p_cfg->mtu = p_ccb->peer_cfg.mtu;
1986 }
1987
1988 /* Verify that the flush timeout is a valid value (0 is illegal) */
1989 if (p_cfg->flush_to_present) {
1990 if (!p_cfg->flush_to) {
1991 p_cfg->flush_to = 0xFFFF; /* Infinite retransmissions (spec default) */
1992 flush_to_ok = FALSE;
1993 } else { /* Save the accepted value in case of renegotiation */
1994 p_ccb->peer_cfg.flush_to_present = TRUE;
1995 p_ccb->peer_cfg.flush_to = p_cfg->flush_to;
1996 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FLUSH_TO;
1997 }
1998 }
1999 /* Reload flush_to from a previously accepted config request */
2000 else if (p_ccb->peer_cfg.flush_to_present) {
2001 p_cfg->flush_to_present = TRUE;
2002 p_cfg->flush_to = p_ccb->peer_cfg.flush_to;
2003 }
2004
2005 /* Save the QOS settings the the peer is using */
2006 if (p_cfg->qos_present) {
2007 /* Make sure service type is not a reserved value; otherwise let upper
2008 layer decide if acceptable
2009 */
2010 if (p_cfg->qos.service_type <= GUARANTEED) {
2011 p_ccb->peer_cfg.qos = p_cfg->qos;
2012 p_ccb->peer_cfg.qos_present = TRUE;
2013 p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_QOS;
2014 } else { /* Illegal service type value */
2015 p_cfg->qos.service_type = BEST_EFFORT;
2016 qos_type_ok = FALSE;
2017 }
2018 }
2019 /* Reload QOS from a previously accepted config request */
2020 else if (p_ccb->peer_cfg.qos_present) {
2021 p_cfg->qos_present = TRUE;
2022 p_cfg->qos = p_ccb->peer_cfg.qos;
2023 }
2024 #if (CLASSIC_BT_INCLUDED == TRUE)
2025 if ((fcr_status = l2c_fcr_process_peer_cfg_req (p_ccb, p_cfg)) == L2CAP_PEER_CFG_DISCONNECT) {
2026 /* Notify caller to disconnect the channel (incompatible modes) */
2027 p_cfg->result = L2CAP_CFG_FAILED_NO_REASON;
2028 p_cfg->mtu_present = p_cfg->qos_present = p_cfg->flush_to_present = 0;
2029
2030 return (L2CAP_PEER_CFG_DISCONNECT);
2031 }
2032
2033 fcr_ok = (fcr_status == L2CAP_PEER_CFG_OK);
2034 #endif ///CLASSIC_BT_INCLUDED == TRUE
2035
2036 /* Return any unacceptable parameters */
2037 if (mtu_ok && flush_to_ok && qos_type_ok && fcr_ok) {
2038 l2cu_adjust_out_mps (p_ccb);
2039 return (L2CAP_PEER_CFG_OK);
2040 } else {
2041 p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
2042
2043 if (mtu_ok) {
2044 p_cfg->mtu_present = FALSE;
2045 }
2046 if (flush_to_ok) {
2047 p_cfg->flush_to_present = FALSE;
2048 }
2049 if (qos_type_ok) {
2050 p_cfg->qos_present = FALSE;
2051 }
2052 if (fcr_ok) {
2053 p_cfg->fcr_present = FALSE;
2054 }
2055
2056 return (L2CAP_PEER_CFG_UNACCEPTABLE);
2057 }
2058 }
2059
2060
2061 /*******************************************************************************
2062 **
2063 ** Function l2cu_process_peer_cfg_rsp
2064 **
2065 ** Description This function is called when the peer sends us a "config response"
2066 ** message. It extracts the configuration of interest and saves
2067 ** it in the CCB.
2068 **
2069 ** Returns void
2070 **
2071 *******************************************************************************/
l2cu_process_peer_cfg_rsp(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)2072 void l2cu_process_peer_cfg_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2073 {
2074 /* If we wanted QoS and the peer sends us a positive response with QoS, use his values */
2075 if ( (p_cfg->qos_present) && (p_ccb->our_cfg.qos_present) ) {
2076 p_ccb->our_cfg.qos = p_cfg->qos;
2077 }
2078
2079 if (p_cfg->fcr_present) {
2080 /* Save the retransmission and monitor timeout values */
2081 if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE) {
2082 p_ccb->peer_cfg.fcr.rtrans_tout = p_cfg->fcr.rtrans_tout;
2083 p_ccb->peer_cfg.fcr.mon_tout = p_cfg->fcr.mon_tout;
2084 }
2085
2086 /* Calculate the max number of packets for which we can delay sending an ack */
2087 if (p_cfg->fcr.tx_win_sz < p_ccb->our_cfg.fcr.tx_win_sz) {
2088 p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2089 } else {
2090 p_ccb->fcrb.max_held_acks = p_ccb->our_cfg.fcr.tx_win_sz / 3;
2091 }
2092
2093 L2CAP_TRACE_DEBUG ("l2cu_process_peer_cfg_rsp(): peer tx_win_sz: %d, our tx_win_sz: %d, max_held_acks: %d",
2094 p_cfg->fcr.tx_win_sz, p_ccb->our_cfg.fcr.tx_win_sz, p_ccb->fcrb.max_held_acks);
2095 }
2096 }
2097
2098 /*******************************************************************************
2099 **
2100 ** Function l2cu_process_our_cfg_req
2101 **
2102 ** Description This function is called when we send a "config request"
2103 ** message. It extracts the configuration of interest and saves
2104 ** it in the CCB.
2105 **
2106 ** Returns void
2107 **
2108 *******************************************************************************/
l2cu_process_our_cfg_req(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)2109 void l2cu_process_our_cfg_req (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2110 {
2111 tL2C_LCB *p_lcb;
2112 UINT16 hci_flush_to;
2113
2114 /* Save the QOS settings we are using for transmit */
2115 if (p_cfg->qos_present) {
2116 p_ccb->our_cfg.qos_present = TRUE;
2117 p_ccb->our_cfg.qos = p_cfg->qos;
2118 }
2119
2120 if (p_cfg->fcr_present) {
2121 /* Override FCR options if attempting streaming or basic */
2122 if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE) {
2123 memset(&p_cfg->fcr, 0, sizeof(tL2CAP_FCR_OPTS));
2124 } else {
2125 /* On BR/EDR, timer values are zero in config request */
2126 /* On class 2 AMP, timer value in config request shall be non-0 processing time */
2127 /* timer value in config response shall be greater than received processing time */
2128 p_cfg->fcr.mon_tout = p_cfg->fcr.rtrans_tout = 0;
2129
2130 if (p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE) {
2131 p_cfg->fcr.max_transmit = p_cfg->fcr.tx_win_sz = 0;
2132 }
2133 }
2134
2135 /* Set the threshold to send acks (may be updated in the cfg response) */
2136 p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2137
2138 /* Include FCS option only if peer can handle it */
2139 if (p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_NO_CRC) {
2140 /* FCS check can be bypassed if peer also desires to bypass */
2141 if (p_cfg->fcs_present && p_cfg->fcs == L2CAP_CFG_FCS_BYPASS) {
2142 p_ccb->bypass_fcs |= L2CAP_CFG_FCS_OUR;
2143 }
2144 } else {
2145 p_cfg->fcs_present = FALSE;
2146 }
2147 } else {
2148 p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
2149 }
2150
2151 p_ccb->our_cfg.fcr.mode = p_cfg->fcr.mode;
2152 p_ccb->our_cfg.fcr_present = p_cfg->fcr_present;
2153
2154 /* Check the flush timeout. If it is lower than the current one used */
2155 /* then we need to adjust the flush timeout sent to the controller */
2156 if (p_cfg->flush_to_present) {
2157 if ((p_cfg->flush_to == 0) || (p_cfg->flush_to == L2CAP_NO_AUTOMATIC_FLUSH)) {
2158 /* don't send invalid flush timeout */
2159 /* SPEC: The sender of the Request shall specify its flush timeout value */
2160 /* if it differs from the default value of 0xFFFF */
2161 p_cfg->flush_to_present = FALSE;
2162 } else {
2163 p_ccb->our_cfg.flush_to = p_cfg->flush_to;
2164 p_lcb = p_ccb->p_lcb;
2165
2166 if (p_cfg->flush_to < p_lcb->link_flush_tout) {
2167 p_lcb->link_flush_tout = p_cfg->flush_to;
2168
2169 /* If the timeout is within range of HCI, set the flush timeout */
2170 if (p_cfg->flush_to <= ((HCI_MAX_AUTO_FLUSH_TOUT * 5) / 8)) {
2171 /* Convert flush timeout to 0.625 ms units, with round */
2172 hci_flush_to = ((p_cfg->flush_to * 8) + 3) / 5;
2173 btsnd_hcic_write_auto_flush_tout (p_lcb->handle, hci_flush_to);
2174 }
2175 }
2176 }
2177 }
2178 }
2179
2180
2181 /*******************************************************************************
2182 **
2183 ** Function l2cu_process_our_cfg_rsp
2184 **
2185 ** Description This function is called when we send the peer a "config response"
2186 ** message. It extracts the configuration of interest and saves
2187 ** it in the CCB.
2188 **
2189 ** Returns void
2190 **
2191 *******************************************************************************/
2192 #if (CLASSIC_BT_INCLUDED == TRUE)
l2cu_process_our_cfg_rsp(tL2C_CCB * p_ccb,tL2CAP_CFG_INFO * p_cfg)2193 void l2cu_process_our_cfg_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
2194 {
2195 /* If peer wants QoS, we are allowed to change the values in a positive response */
2196 if ( (p_cfg->qos_present) && (p_ccb->peer_cfg.qos_present) ) {
2197 p_ccb->peer_cfg.qos = p_cfg->qos;
2198 } else {
2199 p_cfg->qos_present = FALSE;
2200 }
2201
2202 l2c_fcr_adj_our_rsp_options (p_ccb, p_cfg);
2203 }
2204 #endif ///CLASSIC_BT_INCLUDED == TRUE
2205
2206
2207 /*******************************************************************************
2208 **
2209 ** Function l2cu_device_reset
2210 **
2211 ** Description This function is called when reset of the device is
2212 ** completed. For all active connection simulate HCI_DISC
2213 **
2214 ** Returns void
2215 **
2216 *******************************************************************************/
l2cu_device_reset(void)2217 void l2cu_device_reset (void)
2218 {
2219 list_node_t *p_node = NULL;
2220 tL2C_LCB *p_lcb = NULL;
2221 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
2222 p_lcb = list_node(p_node);
2223 if ((p_lcb->in_use) && (p_lcb->handle != HCI_INVALID_HANDLE)) {
2224 l2c_link_hci_disc_comp (p_lcb->handle, (UINT8) - 1);
2225 }
2226 }
2227 #if (BLE_INCLUDED == TRUE)
2228 l2cb.is_ble_connecting = FALSE;
2229 #endif
2230 }
2231
2232 /*******************************************************************************
2233 **
2234 ** Function l2cu_create_conn
2235 **
2236 ** Description This function initiates an acl connection via HCI
2237 **
2238 ** Returns TRUE if successful, FALSE if gki get buffer fails.
2239 **
2240 *******************************************************************************/
l2cu_create_conn(tL2C_LCB * p_lcb,tBT_TRANSPORT transport)2241 BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport)
2242 {
2243 #if BTM_SCO_INCLUDED == TRUE
2244 BOOLEAN is_sco_active;
2245 #endif
2246 list_node_t *p_node = NULL;
2247 tL2C_LCB *p_lcb_cur = NULL;
2248
2249 #if (BLE_INCLUDED == TRUE)
2250 tBT_DEVICE_TYPE dev_type;
2251 tBLE_ADDR_TYPE addr_type = p_lcb->open_addr_type;
2252 if(addr_type == BLE_ADDR_UNKNOWN_TYPE) {
2253 BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type);
2254 }
2255
2256 if (transport == BT_TRANSPORT_LE) {
2257 if (!controller_get_interface()->supports_ble()) {
2258 return FALSE;
2259 }
2260 if(addr_type > BLE_ADDR_TYPE_MAX) {
2261 addr_type = BLE_ADDR_PUBLIC;
2262 }
2263 p_lcb->ble_addr_type = addr_type;
2264 p_lcb->transport = BT_TRANSPORT_LE;
2265
2266 return (l2cble_create_conn(p_lcb));
2267 }
2268 #endif
2269
2270 /* If there is a connection where we perform as a slave, try to switch roles
2271 for this connection */
2272 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
2273 p_lcb_cur = list_node(p_node);
2274 if (p_lcb_cur == p_lcb) {
2275 continue;
2276 }
2277
2278 if ((p_lcb_cur->in_use) && (p_lcb_cur->link_role == HCI_ROLE_SLAVE)) {
2279
2280 #if BTM_SCO_INCLUDED == TRUE
2281 /* The LMP_switch_req shall be sent only if the ACL logical transport
2282 is in active mode, when encryption is disabled, and all synchronous
2283 logical transports on the same physical link are disabled." */
2284
2285 /* Check if there is any SCO Active on this BD Address */
2286 is_sco_active = btm_is_sco_active_by_bdaddr(p_lcb_cur->remote_bd_addr);
2287
2288 L2CAP_TRACE_API ("l2cu_create_conn - btm_is_sco_active_by_bdaddr() is_sco_active = %s", \
2289 (is_sco_active == TRUE) ? "TRUE" : "FALSE");
2290
2291 if (is_sco_active == TRUE) {
2292 continue; /* No Master Slave switch not allowed when SCO Active */
2293 }
2294 #endif
2295 /*4_1_TODO check if btm_cb.devcb.local_features to be used instead */
2296 if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures())) {
2297 /* mark this lcb waiting for switch to be completed and
2298 start switch on the other one */
2299 p_lcb->link_state = LST_CONNECTING_WAIT_SWITCH;
2300 p_lcb->link_role = HCI_ROLE_MASTER;
2301
2302 if (BTM_SwitchRole (p_lcb_cur->remote_bd_addr, HCI_ROLE_MASTER, NULL) == BTM_CMD_STARTED) {
2303 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_LINK_ROLE_SWITCH_TOUT);
2304 return (TRUE);
2305 }
2306 }
2307 }
2308 }
2309
2310 p_lcb->link_state = LST_CONNECTING;
2311
2312 return (l2cu_create_conn_after_switch (p_lcb));
2313 }
2314
2315 /*******************************************************************************
2316 **
2317 ** Function l2cu_get_num_hi_priority
2318 **
2319 ** Description Gets the number of high priority channels.
2320 **
2321 ** Returns
2322 **
2323 *******************************************************************************/
l2cu_get_num_hi_priority(void)2324 UINT8 l2cu_get_num_hi_priority (void)
2325 {
2326 UINT8 no_hi = 0;
2327 list_node_t *p_node = NULL;
2328 tL2C_LCB *p_lcb = NULL;
2329
2330 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
2331 p_lcb = list_node(p_node);
2332 if ((p_lcb->in_use) && (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2333 no_hi++;
2334 }
2335 }
2336 return no_hi;
2337 }
2338
2339
2340 /*******************************************************************************
2341 **
2342 ** Function l2cu_create_conn_after_switch
2343 **
2344 ** Description This function initiates an acl connection via HCI
2345 ** If switch required to create connection it is already done.
2346 **
2347 ** Returns TRUE if successful, FALSE if osi get buffer fails.
2348 **
2349 *******************************************************************************/
2350
l2cu_create_conn_after_switch(tL2C_LCB * p_lcb)2351 BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb)
2352 {
2353 UINT8 allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2354 tBTM_INQ_INFO *p_inq_info;
2355 UINT8 page_scan_rep_mode;
2356 UINT8 page_scan_mode;
2357 UINT16 clock_offset;
2358 UINT8 *p_features;
2359 UINT16 num_acl = BTM_GetNumAclLinks();
2360 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_lcb->remote_bd_addr);
2361 UINT8 no_hi_prio_chs = l2cu_get_num_hi_priority();
2362
2363 p_features = BTM_ReadLocalFeatures();
2364
2365 L2CAP_TRACE_DEBUG ("l2cu_create_conn_after_switch :%d num_acl:%d no_hi: %d is_bonding:%d",
2366 l2cb.disallow_switch, num_acl, no_hi_prio_chs, p_lcb->is_bonding);
2367 /* FW team says that we can participant in 4 piconets
2368 * typically 3 piconet + 1 for scanning.
2369 * We can enhance the code to count the number of piconets later. */
2370 if ( ((!l2cb.disallow_switch && (num_acl < 3)) || (p_lcb->is_bonding && (no_hi_prio_chs == 0)))
2371 && HCI_SWITCH_SUPPORTED(p_features)) {
2372 allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2373 } else {
2374 allow_switch = HCI_CR_CONN_NOT_ALLOW_SWITCH;
2375 }
2376
2377 p_lcb->link_state = LST_CONNECTING;
2378
2379 /* Check with the BT manager if details about remote device are known */
2380 if ((p_inq_info = BTM_InqDbRead(p_lcb->remote_bd_addr)) != NULL) {
2381 page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode;
2382 page_scan_mode = p_inq_info->results.page_scan_mode;
2383 clock_offset = (UINT16)(p_inq_info->results.clock_offset);
2384 } else {
2385 /* No info known. Use default settings */
2386 page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R1;
2387 page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;
2388
2389 clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0;
2390 }
2391
2392 if (!btsnd_hcic_create_conn (p_lcb->remote_bd_addr,
2393 ( HCI_PKT_TYPES_MASK_DM1 | HCI_PKT_TYPES_MASK_DH1
2394 | HCI_PKT_TYPES_MASK_DM3 | HCI_PKT_TYPES_MASK_DH3
2395 | HCI_PKT_TYPES_MASK_DM5 | HCI_PKT_TYPES_MASK_DH5 ),
2396 page_scan_rep_mode,
2397 page_scan_mode,
2398 clock_offset,
2399 allow_switch))
2400
2401 {
2402 L2CAP_TRACE_ERROR ("L2CAP - no buffer for l2cu_create_conn");
2403 l2cu_release_lcb (p_lcb);
2404 return (FALSE);
2405 }
2406
2407 btm_acl_update_busy_level (BTM_BLI_PAGE_EVT);
2408
2409 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK,
2410 L2CAP_LINK_CONNECT_TOUT);
2411
2412 return (TRUE);
2413 }
2414
2415
2416 /*******************************************************************************
2417 **
2418 ** Function l2cu_find_lcb_by_state
2419 **
2420 ** Description Look through all active LCBs for a match based on the
2421 ** LCB state.
2422 **
2423 ** Returns pointer to first matched LCB, or NULL if no match
2424 **
2425 *******************************************************************************/
l2cu_find_lcb_by_state(tL2C_LINK_STATE state)2426 tL2C_LCB *l2cu_find_lcb_by_state (tL2C_LINK_STATE state)
2427 {
2428 list_node_t *p_node = NULL;
2429 tL2C_LCB *p_lcb = NULL;
2430
2431 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
2432 p_lcb = list_node(p_node);
2433 if ((p_lcb->in_use) && (p_lcb->link_state == state)) {
2434 return (p_lcb);
2435 }
2436 }
2437
2438 /* If here, no match found */
2439 return (NULL);
2440 }
2441
2442
2443 /*******************************************************************************
2444 **
2445 ** Function l2cu_lcb_disconnecting
2446 **
2447 ** Description On each active lcb, check if the lcb is in disconnecting
2448 ** state, or if there are no ccb's on the lcb (implying
2449 idle timeout is running), or if last ccb on the link
2450 is in disconnecting state.
2451 **
2452 ** Returns TRUE if any of above conditions met, FALSE otherwise
2453 **
2454 *******************************************************************************/
l2cu_lcb_disconnecting(void)2455 BOOLEAN l2cu_lcb_disconnecting (void)
2456 {
2457 tL2C_LCB *p_lcb;
2458 tL2C_CCB *p_ccb;
2459 BOOLEAN status = FALSE;
2460 list_node_t *p_node = NULL;
2461
2462 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
2463 p_lcb = list_node(p_node);
2464 if (p_lcb->in_use) {
2465 /* no ccbs on lcb, or lcb is in disconnecting state */
2466 if ((!p_lcb->ccb_queue.p_first_ccb) || (p_lcb->link_state == LST_DISCONNECTING)) {
2467 status = TRUE;
2468 break;
2469 }
2470 /* only one ccb left on lcb */
2471 else if (p_lcb->ccb_queue.p_first_ccb == p_lcb->ccb_queue.p_last_ccb) {
2472 p_ccb = p_lcb->ccb_queue.p_first_ccb;
2473
2474 if ((p_ccb->in_use) &&
2475 ((p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP) ||
2476 (p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))) {
2477 status = TRUE;
2478 break;
2479 }
2480 }
2481 }
2482 }
2483 return status;
2484 }
2485
2486
2487 /*******************************************************************************
2488 **
2489 ** Function l2cu_set_acl_priority
2490 **
2491 ** Description Sets the transmission priority for a channel.
2492 ** (For initial implementation only two values are valid.
2493 ** L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH).
2494 **
2495 ** Returns TRUE if a valid channel, else FALSE
2496 **
2497 *******************************************************************************/
2498
l2cu_set_acl_priority(BD_ADDR bd_addr,UINT8 priority,BOOLEAN reset_after_rs)2499 BOOLEAN l2cu_set_acl_priority (BD_ADDR bd_addr, UINT8 priority, BOOLEAN reset_after_rs)
2500 {
2501 tL2C_LCB *p_lcb;
2502 UINT8 *pp;
2503 UINT8 command[HCI_BRCM_ACL_PRIORITY_PARAM_SIZE];
2504 UINT8 vs_param;
2505
2506 //APPL_TRACE_EVENT("SET ACL PRIORITY %d", priority);
2507
2508 /* Find the link control block for the acl channel */
2509 if ((p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR)) == NULL) {
2510 L2CAP_TRACE_WARNING ("L2CAP - no LCB for L2CA_SetAclPriority");
2511 return (FALSE);
2512 }
2513
2514 if (BTM_IS_BRCM_CONTROLLER()) {
2515 /* Called from above L2CAP through API; send VSC if changed */
2516 if ((!reset_after_rs && (priority != p_lcb->acl_priority)) ||
2517 /* Called because of a master/slave role switch; if high resend VSC */
2518 ( reset_after_rs && p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2519 pp = command;
2520
2521 vs_param = (priority == L2CAP_PRIORITY_HIGH) ? HCI_BRCM_ACL_PRIORITY_HIGH : HCI_BRCM_ACL_PRIORITY_LOW;
2522
2523 UINT16_TO_STREAM (pp, p_lcb->handle);
2524 UINT8_TO_STREAM (pp, vs_param);
2525
2526 BTM_VendorSpecificCommand (HCI_BRCM_SET_ACL_PRIORITY, HCI_BRCM_ACL_PRIORITY_PARAM_SIZE, command, NULL);
2527
2528 /* Adjust lmp buffer allocation for this channel if priority changed */
2529 if (p_lcb->acl_priority != priority) {
2530 p_lcb->acl_priority = priority;
2531 l2c_link_adjust_allocation();
2532 }
2533 }
2534 }
2535 return (TRUE);
2536 }
2537
2538 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
2539 /******************************************************************************
2540 **
2541 ** Function l2cu_set_non_flushable_pbf
2542 **
2543 ** Description set L2CAP_PKT_START_NON_FLUSHABLE if controller supoorts
2544 **
2545 ** Returns void
2546 **
2547 *******************************************************************************/
l2cu_set_non_flushable_pbf(BOOLEAN is_supported)2548 void l2cu_set_non_flushable_pbf (BOOLEAN is_supported)
2549 {
2550 if (is_supported) {
2551 l2cb.non_flushable_pbf = (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT);
2552 } else {
2553 l2cb.non_flushable_pbf = (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT);
2554 }
2555 }
2556 #endif
2557
2558 /*******************************************************************************
2559 **
2560 ** Function l2cu_resubmit_pending_sec_req
2561 **
2562 ** Description This function is called when required security procedures
2563 ** are completed and any pending requests can be re-submitted.
2564 **
2565 ** Returns void
2566 **
2567 *******************************************************************************/
2568 #if (CLASSIC_BT_INCLUDED == TRUE)
l2cu_resubmit_pending_sec_req(BD_ADDR p_bda)2569 void l2cu_resubmit_pending_sec_req (BD_ADDR p_bda)
2570 {
2571 tL2C_LCB *p_lcb;
2572 tL2C_CCB *p_ccb;
2573 tL2C_CCB *p_next_ccb;
2574 L2CAP_TRACE_DEBUG ("l2cu_resubmit_pending_sec_req p_bda: %p", p_bda);
2575 list_node_t *p_node = NULL;
2576
2577 /* If we are called with a BDA, only resubmit for that BDA */
2578 if (p_bda) {
2579 p_lcb = l2cu_find_lcb_by_bd_addr (p_bda, BT_TRANSPORT_BR_EDR);
2580 /* If we don't have one, this is an error */
2581 if (p_lcb) {
2582 /* For all channels, send the event through their FSMs */
2583 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2584 p_next_ccb = p_ccb->p_next_ccb;
2585 l2c_csm_execute (p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2586 }
2587 } else {
2588 L2CAP_TRACE_WARNING ("l2cu_resubmit_pending_sec_req - unknown BD_ADDR");
2589 }
2590 } else {
2591 /* No BDA pasesed in, so check all links */
2592 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
2593 p_lcb = list_node(p_node);
2594 if (p_lcb->in_use) {
2595 /* For all channels, send the event through their FSMs */
2596 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2597 p_next_ccb = p_ccb->p_next_ccb;
2598 l2c_csm_execute (p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2599 }
2600 }
2601 }
2602 }
2603 }
2604 #endif ///CLASSIC_BT_INCLUDED == TRUE
2605
2606 #if L2CAP_CONFORMANCE_TESTING == TRUE
2607 /*******************************************************************************
2608 **
2609 ** Function l2cu_set_info_rsp_mask
2610 **
2611 ** Description This function allows the script wrapper to change the
2612 ** info resp mask for conformance testing.
2613 **
2614 ** Returns pointer to CCB, or NULL if none
2615 **
2616 *******************************************************************************/
l2cu_set_info_rsp_mask(UINT32 mask)2617 void l2cu_set_info_rsp_mask (UINT32 mask)
2618 {
2619 l2cb.test_info_resp = mask;
2620 }
2621 #endif /* L2CAP_CONFORMANCE_TESTING */
2622
2623 /*******************************************************************************
2624 **
2625 ** Function l2cu_adjust_out_mps
2626 **
2627 ** Description Sets our MPS based on current controller capabilities
2628 **
2629 ** Returns void
2630 **
2631 *******************************************************************************/
l2cu_adjust_out_mps(tL2C_CCB * p_ccb)2632 void l2cu_adjust_out_mps (tL2C_CCB *p_ccb)
2633 {
2634 UINT16 packet_size;
2635
2636 /* on the tx side MTU is selected based on packet size of the controller */
2637 packet_size = btm_get_max_packet_size (p_ccb->p_lcb->remote_bd_addr);
2638
2639 if (packet_size <= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD + L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN)) {
2640 /* something is very wrong */
2641 L2CAP_TRACE_DEBUG ("l2cu_adjust_out_mps bad packet size: %u will use MPS: %u", packet_size, p_ccb->peer_cfg.fcr.mps);
2642 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2643 } else {
2644 packet_size -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD + L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN);
2645
2646 /* We try to negotiate MTU that each packet can be split into whole
2647 number of max packets. For example if link is 1.2 max packet size is 339 bytes.
2648 At first calculate how many whole packets it is. MAX L2CAP is 1691 + 4 overhead.
2649 1695, that will be 5 Dh5 packets. Now maximum L2CAP packet is
2650 5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.
2651
2652 For EDR 2.0 packet size is 1027. So we better send RFCOMM packet as 1 3DH5 packet
2653 1 * 1027 = 1027. Minus 4 bytes L2CAP header 1023. */
2654 if (p_ccb->peer_cfg.fcr.mps >= packet_size) {
2655 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps / packet_size * packet_size;
2656 } else {
2657 p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2658 }
2659
2660 L2CAP_TRACE_DEBUG ("l2cu_adjust_out_mps use %d Based on peer_cfg.fcr.mps: %u packet_size: %u",
2661 p_ccb->tx_mps, p_ccb->peer_cfg.fcr.mps, packet_size);
2662 }
2663 }
2664
2665
2666 /*******************************************************************************
2667 **
2668 ** Function l2cu_initialize_fixed_ccb
2669 **
2670 ** Description Initialize a fixed channel's CCB
2671 **
2672 ** Returns TRUE or FALSE
2673 **
2674 *******************************************************************************/
l2cu_initialize_fixed_ccb(tL2C_LCB * p_lcb,UINT16 fixed_cid,tL2CAP_FCR_OPTS * p_fcr)2675 BOOLEAN l2cu_initialize_fixed_ccb (tL2C_LCB *p_lcb, UINT16 fixed_cid, tL2CAP_FCR_OPTS *p_fcr)
2676 {
2677 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2678 tL2C_CCB *p_ccb;
2679 /* If we already have a CCB, then simply return */
2680 if (p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] != NULL) {
2681 return (TRUE);
2682 }
2683
2684 if ((p_ccb = l2cu_allocate_ccb (NULL, 0)) == NULL) {
2685 return (FALSE);
2686 }
2687
2688 btu_stop_timer(&p_lcb->timer_entry);
2689
2690 /* Set CID for the connection */
2691 p_ccb->local_cid = fixed_cid;
2692 p_ccb->remote_cid = fixed_cid;
2693
2694 p_ccb->is_flushable = FALSE;
2695
2696 p_ccb->timer_entry.param = (TIMER_PARAM_TYPE)p_ccb;
2697
2698
2699 if (p_fcr) {
2700 /* Set the FCR parameters. For now, we will use default pools */
2701 p_ccb->our_cfg.fcr = p_ccb->peer_cfg.fcr = *p_fcr;
2702
2703 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
2704 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
2705 p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
2706 p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
2707
2708 p_ccb->fcrb.max_held_acks = p_fcr->tx_win_sz / 3;
2709 }
2710
2711 /* Link ccb to lcb and lcb to ccb */
2712 p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = p_ccb;
2713 p_ccb->p_lcb = p_lcb;
2714
2715 /* There is no configuration, so if the link is up, the channel is up */
2716 if (p_lcb->link_state == LST_CONNECTED) {
2717 p_ccb->chnl_state = CST_OPEN;
2718 }
2719
2720 /* Set the default idle timeout value to use */
2721 p_ccb->fixed_chnl_idle_tout = l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].default_idle_tout;
2722 #endif
2723 return (TRUE);
2724 }
2725
2726 /*******************************************************************************
2727 **
2728 ** Function l2cu_no_dynamic_ccbs
2729 **
2730 ** Description Handles the case when there are no more dynamic CCBs. If there
2731 ** are any fixed CCBs, start the longest of the fixed CCB timeouts,
2732 ** otherwise start the default link idle timeout or disconnect.
2733 **
2734 ** Returns void
2735 **
2736 *******************************************************************************/
l2cu_no_dynamic_ccbs(tL2C_LCB * p_lcb)2737 void l2cu_no_dynamic_ccbs (tL2C_LCB *p_lcb)
2738 {
2739 #if (SMP_INCLUDED == TRUE)
2740 tBTM_STATUS rc;
2741 #endif ///SMP_INCLUDED == TRUE
2742 UINT16 timeout = p_lcb->idle_timeout;
2743
2744 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2745 int xx;
2746
2747 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2748 if ( (p_lcb->p_fixed_ccbs[xx] != NULL) && (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout > timeout) ) {
2749 timeout = p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout;
2750 }
2751 }
2752 #endif
2753
2754 /* If the link is pairing, do not mess with the timeouts */
2755 if (p_lcb->is_bonding) {
2756 return;
2757 }
2758
2759 if (timeout == 0) {
2760 L2CAP_TRACE_DEBUG ("l2cu_no_dynamic_ccbs() IDLE timer 0, disconnecting link");
2761 #if (SMP_INCLUDED == TRUE)
2762 rc = btm_sec_disconnect (p_lcb->handle, HCI_ERR_PEER_USER);
2763 if (rc == BTM_CMD_STARTED) {
2764 l2cu_process_fixed_disc_cback(p_lcb);
2765 p_lcb->link_state = LST_DISCONNECTING;
2766 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2767 } else if (rc == BTM_SUCCESS) {
2768 l2cu_process_fixed_disc_cback(p_lcb);
2769 /* BTM SEC will make sure that link is release (probably after pairing is done) */
2770 p_lcb->link_state = LST_DISCONNECTING;
2771 timeout = 0xFFFF;
2772 } else if ( (p_lcb->is_bonding)
2773 && (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) ) {
2774 l2cu_process_fixed_disc_cback(p_lcb);
2775 p_lcb->link_state = LST_DISCONNECTING;
2776 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2777 } else {
2778 /* probably no buffer to send disconnect */
2779 timeout = BT_1SEC_TIMEOUT;
2780 }
2781 #else
2782 if (btsnd_hcic_disconnect (p_lcb->handle, HCI_ERR_PEER_USER)) {
2783 l2cu_process_fixed_disc_cback(p_lcb);
2784 p_lcb->link_state = LST_DISCONNECTING;
2785 timeout = L2CAP_LINK_DISCONNECT_TOUT;
2786 } else {
2787 timeout = BT_1SEC_TIMEOUT;
2788 }
2789 #endif ///SMP_INCLUDED == TRUE
2790
2791 }
2792
2793 if (timeout != 0xFFFF) {
2794 L2CAP_TRACE_DEBUG ("l2cu_no_dynamic_ccbs() starting IDLE timeout: %d", timeout);
2795 btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, timeout);
2796 } else {
2797 btu_stop_timer(&p_lcb->timer_entry);
2798 }
2799 }
2800
2801 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2802 /*******************************************************************************
2803 **
2804 ** Function l2cu_process_fixed_chnl_resp
2805 **
2806 ** Description handle a fixed channel response (or lack thereof)
2807 ** if the link failed, or a fixed channel response was
2808 ** not received, the bitfield is all zeros.
2809 **
2810 *******************************************************************************/
l2cu_process_fixed_chnl_resp(tL2C_LCB * p_lcb)2811 void l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb)
2812 {
2813 L2CAP_TRACE_DEBUG("%s",__func__);
2814 #if (BLE_INCLUDED == TRUE)
2815 if (p_lcb->transport == BT_TRANSPORT_BR_EDR) {
2816 /* ignore all not assigned BR/EDR channels */
2817 p_lcb->peer_chnl_mask[0] &= (L2CAP_FIXED_CHNL_SIG_BIT | \
2818 L2CAP_FIXED_CHNL_CNCTLESS_BIT | \
2819 L2CAP_FIXED_CHNL_SMP_BR_BIT);
2820 } else {
2821 p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
2822 }
2823 #endif
2824
2825 /* Tell all registered fixed channels about the connection */
2826 for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2827 #if BLE_INCLUDED == TRUE
2828 /* skip sending LE fix channel callbacks on BR/EDR links */
2829 if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
2830 xx + L2CAP_FIRST_FIXED_CHNL >= L2CAP_ATT_CID &&
2831 xx + L2CAP_FIRST_FIXED_CHNL <= L2CAP_SMP_CID) {
2832 continue;
2833 }
2834 #endif
2835 if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
2836 if (p_lcb->peer_chnl_mask[(xx + L2CAP_FIRST_FIXED_CHNL) / 8]
2837 & (1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8))) {
2838 if (p_lcb->p_fixed_ccbs[xx]) {
2839 p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
2840 }
2841 #if BLE_INCLUDED == TRUE
2842 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2843 p_lcb->remote_bd_addr, TRUE, 0, p_lcb->transport);
2844 #else
2845 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2846 p_lcb->remote_bd_addr, TRUE, 0, BT_TRANSPORT_BR_EDR);
2847 #endif
2848 } else {
2849 #if BLE_INCLUDED == TRUE
2850 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2851 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2852 #else
2853 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2854 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2855 #endif
2856
2857 if (p_lcb->p_fixed_ccbs[xx]) {
2858 l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
2859 p_lcb->p_fixed_ccbs[xx] = NULL;
2860 }
2861 }
2862 }
2863 }
2864 }
2865 #endif
2866
2867
2868 /*******************************************************************************
2869 **
2870 ** Function l2cu_process_fixed_disc_cback
2871 **
2872 ** Description send l2cap fixed channel disconnection callback to application
2873 **
2874 **
2875 ** Returns void
2876 **
2877 *******************************************************************************/
l2cu_process_fixed_disc_cback(tL2C_LCB * p_lcb)2878 void l2cu_process_fixed_disc_cback (tL2C_LCB *p_lcb)
2879 {
2880 #if (L2CAP_NUM_FIXED_CHNLS > 0)
2881
2882 /* Select peer channels mask to use depending on transport */
2883 UINT8 peer_channel_mask = p_lcb->peer_chnl_mask[0];
2884
2885 // For LE, reset the stored peer channel mask
2886 if (p_lcb->transport == BT_TRANSPORT_LE) {
2887 p_lcb->peer_chnl_mask[0] = 0;
2888 }
2889
2890 for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2891 if (p_lcb->p_fixed_ccbs[xx]) {
2892 if (p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb) {
2893 tL2C_CCB *p_l2c_chnl_ctrl_block;
2894 p_l2c_chnl_ctrl_block = p_lcb->p_fixed_ccbs[xx];
2895 p_lcb->p_fixed_ccbs[xx] = NULL;
2896 l2cu_release_ccb(p_l2c_chnl_ctrl_block);
2897 #if BLE_INCLUDED == TRUE
2898 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2899 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2900 #else
2901 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2902 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2903 #endif
2904 }
2905 } else if ( (peer_channel_mask & (1 << (xx + L2CAP_FIRST_FIXED_CHNL)))
2906 && (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) ) {
2907 #if BLE_INCLUDED == TRUE
2908 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2909 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, p_lcb->transport);
2910 #else
2911 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2912 p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason, BT_TRANSPORT_BR_EDR);
2913 #endif
2914 }
2915 }
2916 #endif
2917 }
2918
2919 #if (BLE_INCLUDED == TRUE)
2920 /*******************************************************************************
2921 **
2922 ** Function l2cu_send_peer_ble_par_req
2923 **
2924 ** Description Build and send a BLE parameter update request message
2925 ** to the peer.
2926 **
2927 ** Returns void
2928 **
2929 *******************************************************************************/
l2cu_send_peer_ble_par_req(tL2C_LCB * p_lcb,UINT16 min_int,UINT16 max_int,UINT16 latency,UINT16 timeout)2930 void l2cu_send_peer_ble_par_req (tL2C_LCB *p_lcb, UINT16 min_int, UINT16 max_int,
2931 UINT16 latency, UINT16 timeout)
2932 {
2933 BT_HDR *p_buf;
2934 UINT8 *p;
2935
2936 /* Create an identifier for this packet */
2937 p_lcb->id++;
2938 l2cu_adj_id (p_lcb, L2CAP_ADJ_ID);
2939
2940 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_UPD_REQ_LEN,
2941 L2CAP_CMD_BLE_UPDATE_REQ, p_lcb->id)) == NULL ) {
2942 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_par_req - no buffer");
2943 return;
2944 }
2945
2946 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2947 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2948
2949 UINT16_TO_STREAM (p, min_int);
2950 UINT16_TO_STREAM (p, max_int);
2951 UINT16_TO_STREAM (p, latency);
2952 UINT16_TO_STREAM (p, timeout);
2953
2954 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
2955 }
2956
2957 /*******************************************************************************
2958 **
2959 ** Function l2cu_send_peer_ble_par_rsp
2960 **
2961 ** Description Build and send a BLE parameter update response message
2962 ** to the peer.
2963 **
2964 ** Returns void
2965 **
2966 *******************************************************************************/
l2cu_send_peer_ble_par_rsp(tL2C_LCB * p_lcb,UINT16 reason,UINT8 rem_id)2967 void l2cu_send_peer_ble_par_rsp (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id)
2968 {
2969 BT_HDR *p_buf;
2970 UINT8 *p;
2971
2972 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_UPD_RSP_LEN,
2973 L2CAP_CMD_BLE_UPDATE_RSP, rem_id)) == NULL ) {
2974 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_par_rsp - no buffer");
2975 return;
2976 }
2977
2978 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2979 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
2980
2981 UINT16_TO_STREAM (p, reason);
2982
2983 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
2984 }
2985
2986 /*******************************************************************************
2987 **
2988 ** Function l2cu_send_peer_ble_credit_based_conn_req
2989 **
2990 ** Description Build and send a BLE packet to establish LE connection oriented
2991 ** L2CAP channel.
2992 **
2993 ** Returns void
2994 **
2995 *******************************************************************************/
l2cu_send_peer_ble_credit_based_conn_req(tL2C_CCB * p_ccb)2996 void l2cu_send_peer_ble_credit_based_conn_req (tL2C_CCB *p_ccb)
2997 {
2998 BT_HDR *p_buf;
2999 UINT8 *p;
3000 tL2C_LCB *p_lcb = NULL;
3001 UINT16 mtu;
3002 UINT16 mps;
3003 UINT16 initial_credit;
3004
3005 if (!p_ccb) {
3006 return;
3007 }
3008 p_lcb = p_ccb->p_lcb;
3009
3010 /* Create an identifier for this packet */
3011 p_ccb->p_lcb->id++;
3012 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3013
3014 p_ccb->local_id = p_ccb->p_lcb->id;
3015
3016 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN,
3017 L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ, p_lcb->id)) == NULL )
3018 {
3019 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
3020 return;
3021 }
3022
3023 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3024 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3025
3026 mtu = p_ccb->local_conn_cfg.mtu;
3027 mps = p_ccb->local_conn_cfg.mps;
3028 initial_credit = p_ccb->local_conn_cfg.credits;
3029
3030 L2CAP_TRACE_DEBUG ("l2cu_send_peer_ble_credit_based_conn_req PSM:0x%04x local_cid:%d\
3031 mtu:%d mps:%d initial_credit:%d", p_ccb->p_rcb->real_psm,\
3032 p_ccb->local_cid, mtu, mps, initial_credit);
3033
3034 UINT16_TO_STREAM (p, p_ccb->p_rcb->real_psm);
3035 UINT16_TO_STREAM (p, p_ccb->local_cid);
3036 UINT16_TO_STREAM (p, mtu);
3037 UINT16_TO_STREAM (p, mps);
3038 UINT16_TO_STREAM (p, initial_credit);
3039
3040 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3041 }
3042
3043 /*******************************************************************************
3044 **
3045 ** Function l2cu_reject_ble_connection
3046 **
3047 ** Description Build and send an L2CAP "Credit based connection res" message
3048 ** to the peer. This function is called for non-success cases.
3049 **
3050 ** Returns void
3051 **
3052 *******************************************************************************/
l2cu_reject_ble_connection(tL2C_LCB * p_lcb,UINT8 rem_id,UINT16 result)3053 void l2cu_reject_ble_connection (tL2C_LCB *p_lcb, UINT8 rem_id, UINT16 result)
3054 {
3055 BT_HDR *p_buf;
3056 UINT8 *p;
3057
3058 if ((p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
3059 L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, rem_id)) == NULL )
3060 {
3061 L2CAP_TRACE_WARNING ("l2cu_reject_ble_connection - no buffer");
3062 return;
3063 }
3064
3065 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3066 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3067
3068 UINT16_TO_STREAM (p, 0); /* Local CID of 0 */
3069 UINT16_TO_STREAM (p, 0); /* MTU */
3070 UINT16_TO_STREAM (p, 0); /* MPS */
3071 UINT16_TO_STREAM (p, 0); /* initial credit */
3072 UINT16_TO_STREAM (p, result);
3073
3074 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3075 }
3076
3077 /*******************************************************************************
3078 **
3079 ** Function l2cu_send_peer_ble_credit_based_conn_res
3080 **
3081 ** Description Build and send an L2CAP "Credit based connection res" message
3082 ** to the peer. This function is called in case of success.
3083 **
3084 ** Returns void
3085 **
3086 *******************************************************************************/
l2cu_send_peer_ble_credit_based_conn_res(tL2C_CCB * p_ccb,UINT16 result)3087 void l2cu_send_peer_ble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result)
3088 {
3089 BT_HDR *p_buf;
3090 UINT8 *p;
3091
3092 L2CAP_TRACE_DEBUG ("l2cu_send_peer_ble_credit_based_conn_res");
3093 if ((p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
3094 L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, p_ccb->remote_id)) == NULL )
3095 {
3096 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_res - no buffer");
3097 return;
3098 }
3099
3100 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3101 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3102
3103 UINT16_TO_STREAM (p, p_ccb->local_cid); /* Local CID */
3104 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.mtu); /* MTU */
3105 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.mps); /* MPS */
3106 UINT16_TO_STREAM (p, p_ccb->local_conn_cfg.credits); /* initial credit */
3107 UINT16_TO_STREAM (p, result);
3108
3109 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, p_buf);
3110 }
3111
3112 /*******************************************************************************
3113 **
3114 ** Function l2cu_send_peer_ble_flow_control_credit
3115 **
3116 ** Description Build and send a BLE packet to give credits to peer device
3117 ** for LE connection oriented L2CAP channel.
3118 **
3119 ** Returns void
3120 **
3121 *******************************************************************************/
l2cu_send_peer_ble_flow_control_credit(tL2C_CCB * p_ccb,UINT16 credit_value)3122 void l2cu_send_peer_ble_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value)
3123 {
3124 BT_HDR *p_buf;
3125 UINT8 *p;
3126 tL2C_LCB *p_lcb = NULL;
3127
3128 if (!p_ccb) {
3129 return;
3130 }
3131 p_lcb = p_ccb->p_lcb;
3132
3133 /* Create an identifier for this packet */
3134 p_ccb->p_lcb->id++;
3135 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3136
3137 p_ccb->local_id = p_ccb->p_lcb->id;
3138
3139 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN,
3140 L2CAP_CMD_BLE_FLOW_CTRL_CREDIT, p_lcb->id)) == NULL )
3141 {
3142 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
3143 return;
3144 }
3145
3146 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3147 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3148
3149 UINT16_TO_STREAM (p, p_ccb->local_cid);
3150 UINT16_TO_STREAM (p, credit_value);
3151
3152 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3153 }
3154
3155 /*******************************************************************************
3156 **
3157 ** Function l2cu_send_peer_ble_credit_based_conn_req
3158 **
3159 ** Description Build and send a BLE packet to disconnect LE connection oriented
3160 ** L2CAP channel.
3161 **
3162 ** Returns void
3163 **
3164 *******************************************************************************/
l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB * p_ccb)3165 void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB *p_ccb)
3166 {
3167 BT_HDR *p_buf;
3168 UINT8 *p;
3169 tL2C_LCB *p_lcb = NULL;
3170 L2CAP_TRACE_DEBUG ("%s",__func__);
3171
3172 if (!p_ccb) {
3173 return;
3174 }
3175 p_lcb = p_ccb->p_lcb;
3176
3177 /* Create an identifier for this packet */
3178 p_ccb->p_lcb->id++;
3179 l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
3180
3181 p_ccb->local_id = p_ccb->p_lcb->id;
3182 if ((p_buf = l2cu_build_header (p_lcb, L2CAP_DISC_REQ_LEN,
3183 L2CAP_CMD_DISC_REQ, p_lcb->id)) == NULL )
3184 {
3185 L2CAP_TRACE_WARNING ("l2cu_send_peer_ble_credit_based_disconn_req - no buffer");
3186 return;
3187 }
3188
3189 p = (UINT8 *)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3190 L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
3191
3192 UINT16_TO_STREAM (p, p_ccb->remote_cid);
3193 UINT16_TO_STREAM (p,p_ccb->local_cid);
3194
3195 l2c_link_check_send_pkts (p_lcb, NULL, p_buf);
3196 }
3197
3198 #endif /* BLE_INCLUDED == TRUE */
3199
3200 /*******************************************************************************
3201 ** Functions used by both Full and Light Stack
3202 ********************************************************************************/
3203
3204 /*******************************************************************************
3205 **
3206 ** Function l2cu_find_lcb_by_handle
3207 **
3208 ** Description Look through all active LCBs for a match based on the
3209 ** HCI handle.
3210 **
3211 ** Returns pointer to matched LCB, or NULL if no match
3212 **
3213 *******************************************************************************/
l2cu_find_lcb_by_handle(UINT16 handle)3214 tL2C_LCB *l2cu_find_lcb_by_handle (UINT16 handle)
3215 {
3216 list_node_t *p_node = NULL;
3217 tL2C_LCB *p_lcb = NULL;
3218 for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
3219 p_lcb = list_node(p_node);
3220 if ((p_lcb->in_use) && (p_lcb->handle == handle)) {
3221 return (p_lcb);
3222 }
3223 }
3224
3225 /* If here, no match found */
3226 return (NULL);
3227 }
3228
3229 /*******************************************************************************
3230 **
3231 ** Function l2cu_find_ccb_by_cid
3232 **
3233 ** Description Look through all active CCBs on a link for a match based
3234 ** on the local CID. If passed the link pointer is NULL, all
3235 ** active links are searched.
3236 **
3237 ** Returns pointer to matched CCB, or NULL if no match
3238 **
3239 *******************************************************************************/
l2cu_find_ccb_in_list(void * p_ccb_node,void * p_local_cid)3240 bool l2cu_find_ccb_in_list(void *p_ccb_node, void *p_local_cid)
3241 {
3242 tL2C_CCB *p_ccb = (tL2C_CCB *)p_ccb_node;
3243 uint8_t local_cid = *((uint8_t *)p_local_cid);
3244
3245 if (p_ccb->local_cid == local_cid && p_ccb->in_use) {
3246 return FALSE;
3247 }
3248 return TRUE;
3249 }
3250
l2cu_find_ccb_by_cid(tL2C_LCB * p_lcb,UINT16 local_cid)3251 tL2C_CCB *l2cu_find_ccb_by_cid (tL2C_LCB *p_lcb, UINT16 local_cid)
3252 {
3253 tL2C_CCB *p_ccb = NULL;
3254 #if (L2CAP_UCD_INCLUDED == FALSE)
3255 if (local_cid < L2CAP_BASE_APPL_CID) {
3256 return NULL;
3257 }
3258 #endif //(L2CAP_UCD_INCLUDED == FALSE)
3259 list_node_t *p_node = NULL;
3260
3261 p_node = (list_foreach(l2cb.p_ccb_pool, l2cu_find_ccb_in_list, &local_cid));
3262 if (p_node) {
3263 p_ccb = (tL2C_CCB *)list_node(p_node);
3264
3265 if (p_lcb && p_lcb != p_ccb->p_lcb) {
3266 p_ccb = NULL;
3267 }
3268 }
3269
3270 return (p_ccb);
3271 }
3272
l2cu_find_free_ccb(void)3273 tL2C_CCB *l2cu_find_free_ccb (void)
3274 {
3275 tL2C_CCB *p_ccb = NULL;
3276
3277 list_node_t *p_node = NULL;
3278
3279 for (p_node = list_begin(l2cb.p_ccb_pool); p_node; p_node = list_next(p_node))
3280 {
3281 p_ccb = list_node(p_node);
3282 if(p_ccb && !p_ccb->in_use ) {
3283 return p_ccb;
3284 }
3285 }
3286
3287 return (NULL);
3288 }
3289
3290 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE && CLASSIC_BT_INCLUDED == TRUE)
3291
3292 /******************************************************************************
3293 **
3294 ** Function l2cu_get_next_channel_in_rr
3295 **
3296 ** Description get the next channel to send on a link. It also adjusts the
3297 ** CCB queue to do a basic priority and round-robin scheduling.
3298 **
3299 ** Returns pointer to CCB or NULL
3300 **
3301 *******************************************************************************/
l2cu_get_next_channel_in_rr(tL2C_LCB * p_lcb)3302 static tL2C_CCB *l2cu_get_next_channel_in_rr(tL2C_LCB *p_lcb)
3303 {
3304 tL2C_CCB *p_serve_ccb = NULL;
3305 tL2C_CCB *p_ccb;
3306
3307 int i, j;
3308
3309 /* scan all of priority until finding a channel to serve */
3310 for ( i = 0; (i < L2CAP_NUM_CHNL_PRIORITY) && (!p_serve_ccb); i++ ) {
3311 /* scan all channel within serving priority group until finding a channel to serve */
3312 for ( j = 0; (j < p_lcb->rr_serv[p_lcb->rr_pri].num_ccb) && (!p_serve_ccb); j++) {
3313 /* scaning from next serving channel */
3314 p_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb;
3315
3316 if (!p_ccb) {
3317 L2CAP_TRACE_ERROR("p_serve_ccb is NULL, rr_pri=%d", p_lcb->rr_pri);
3318 return NULL;
3319 }
3320
3321 L2CAP_TRACE_DEBUG("RR scan pri=%d, lcid=0x%04x, q_cout=%d",
3322 p_ccb->ccb_priority, p_ccb->local_cid,
3323 fixed_queue_length(p_ccb->xmit_hold_q));
3324
3325 /* store the next serving channel */
3326 /* this channel is the last channel of its priority group */
3327 if (( p_ccb->p_next_ccb == NULL )
3328 || ( p_ccb->p_next_ccb->ccb_priority != p_ccb->ccb_priority )) {
3329 /* next serving channel is set to the first channel in the group */
3330 p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_first_ccb;
3331 } else {
3332 /* next serving channel is set to the next channel in the group */
3333 p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_ccb->p_next_ccb;
3334 }
3335
3336 if (p_ccb->chnl_state != CST_OPEN) {
3337 continue;
3338 }
3339
3340 /* eL2CAP option in use */
3341 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3342 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3343 continue;
3344 }
3345
3346 if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3347 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3348 continue;
3349 }
3350
3351
3352 #if (CLASSIC_BT_INCLUDED == TRUE)
3353 /* If in eRTM mode, check for window closure */
3354 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3355 continue;
3356 }
3357 #endif ///CLASSIC_BT_INCLUDED == TRUE
3358 }
3359 } else {
3360 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3361 continue;
3362 }
3363 }
3364
3365 /* found a channel to serve */
3366 p_serve_ccb = p_ccb;
3367 /* decrease quota of its priority group */
3368 p_lcb->rr_serv[p_lcb->rr_pri].quota--;
3369 }
3370
3371 /* if there is no more quota of the priority group or no channel to have data to send */
3372 if ((p_lcb->rr_serv[p_lcb->rr_pri].quota == 0) || (!p_serve_ccb)) {
3373 /* serve next priority group */
3374 p_lcb->rr_pri = (p_lcb->rr_pri + 1) % L2CAP_NUM_CHNL_PRIORITY;
3375 /* initialize its quota */
3376 p_lcb->rr_serv[p_lcb->rr_pri].quota = L2CAP_GET_PRIORITY_QUOTA(p_lcb->rr_pri);
3377 }
3378 }
3379
3380 if (p_serve_ccb) {
3381 L2CAP_TRACE_DEBUG("RR service pri=%d, quota=%d, lcid=0x%04x",
3382 p_serve_ccb->ccb_priority,
3383 p_lcb->rr_serv[p_serve_ccb->ccb_priority].quota,
3384 p_serve_ccb->local_cid );
3385 }
3386
3387 return p_serve_ccb;
3388 }
3389
3390 #else /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
3391
3392 /******************************************************************************
3393 **
3394 ** Function l2cu_get_next_channel
3395 **
3396 ** Description get the next channel to send on a link bassed on priority
3397 ** scheduling.
3398 **
3399 ** Returns pointer to CCB or NULL
3400 **
3401 *******************************************************************************/
3402 #if (CLASSIC_BT_INCLUDED == TRUE)
l2cu_get_next_channel(tL2C_LCB * p_lcb)3403 static tL2C_CCB *l2cu_get_next_channel(tL2C_LCB *p_lcb)
3404 {
3405 tL2C_CCB *p_ccb;
3406
3407 /* Get the first CCB with data to send.
3408 */
3409 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) {
3410 if (p_ccb->chnl_state != CST_OPEN) {
3411 continue;
3412 }
3413
3414 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3415 continue;
3416 }
3417
3418 if (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q))
3419 return p_ccb;
3420 }
3421
3422 if (fixed_queue_is_empty(p_ccb->xmit_hold_q))
3423 continue;
3424 }
3425
3426 /* If in eRTM mode, check for window closure */
3427 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3428 continue;
3429 }
3430
3431 /* If here, we found someone */
3432 return p_ccb;
3433 }
3434
3435 return NULL;
3436 }
3437 #endif ///CLASSIC_BT_INCLUDED == TRUE
3438
3439 #endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
3440
3441 /******************************************************************************
3442 **
3443 ** Function l2cu_get_next_buffer_to_send
3444 **
3445 ** Description get the next buffer to send on a link. It also adjusts the
3446 ** CCB queue to do a basic priority and round-robin scheduling.
3447 **
3448 ** Returns pointer to buffer or NULL
3449 **
3450 *******************************************************************************/
3451 BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
3452 {
3453 tL2C_CCB *p_ccb;
3454 BT_HDR *p_buf = NULL;
3455
3456 /* Highest priority are fixed channels */
3457 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3458 int xx;
3459
3460 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3461 if ((p_ccb = p_lcb->p_fixed_ccbs[xx]) == NULL) {
3462 continue;
3463 }
3464
3465 /* eL2CAP option in use */
3466 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3467 #if (CLASSIC_BT_INCLUDED == TRUE)
3468 if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) {
3469 continue;
3470 }
3471
3472 /* No more checks needed if sending from the reatransmit queue */
3473 if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q))
3474 {
3475 if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3476 continue;
3477 }
3478 /* If in eRTM mode, check for window closure */
3479 if ( (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) && (l2c_fcr_is_flow_controlled (p_ccb)) ) {
3480 continue;
3481 }
3482 }
3483 if ((p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0)) != NULL) {
3484 l2cu_check_channel_congestion (p_ccb);
3485 l2cu_set_acl_hci_header (p_buf, p_ccb);
3486 return (p_buf);
3487 }
3488 #else
3489 continue;
3490 #endif ///CLASSIC_BT_INCLUDED == TRUE
3491
3492 } else {
3493 if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3494 p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->xmit_hold_q, 0);
3495 if (NULL == p_buf) {
3496 L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send: No data to be sent");
3497 return (NULL);
3498 }
3499 l2cu_check_channel_congestion (p_ccb);
3500 l2cu_set_acl_hci_header (p_buf, p_ccb);
3501 /* send tx complete */
3502 if (l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb) {
3503 (*l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)(p_ccb->local_cid, 1);
3504 }
3505 return (p_buf);
3506 }
3507 }
3508 }
3509 #endif
3510 #if (CLASSIC_BT_INCLUDED == TRUE)
3511 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
3512 /* get next serving channel in round-robin */
3513 p_ccb = l2cu_get_next_channel_in_rr( p_lcb );
3514 #else
3515 p_ccb = l2cu_get_next_channel( p_lcb );
3516 #endif
3517
3518 /* Return if no buffer */
3519 if (p_ccb == NULL) {
3520 return (NULL);
3521 }
3522
3523 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3524
3525 if ((p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0)) == NULL) {
3526 return (NULL);
3527 }
3528
3529 } else {
3530 p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->xmit_hold_q, 0);
3531 if (NULL == p_buf) {
3532 L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send() #2: No data to be sent");
3533 return (NULL);
3534 }
3535 }
3536
3537 if ( p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb && (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE) ) {
3538 (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1);
3539 }
3540
3541
3542 l2cu_check_channel_congestion (p_ccb);
3543
3544 l2cu_set_acl_hci_header (p_buf, p_ccb);
3545 #endif ///CLASSIC_BT_INCLUDED == TRUE
3546
3547 return (p_buf);
3548 }
3549
3550 /******************************************************************************
3551 **
3552 ** Function l2cu_set_acl_hci_header
3553 **
3554 ** Description Set HCI handle for ACL packet
3555 **
3556 ** Returns None
3557 **
3558 *******************************************************************************/
3559 void l2cu_set_acl_hci_header (BT_HDR *p_buf, tL2C_CCB *p_ccb)
3560 {
3561 UINT8 *p;
3562
3563 /* Set the pointer to the beginning of the data minus 4 bytes for the packet header */
3564 p = (UINT8 *)(p_buf + 1) + p_buf->offset - HCI_DATA_PREAMBLE_SIZE;
3565
3566 #if (BLE_INCLUDED == TRUE)
3567 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3568 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT));
3569
3570 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_ble();
3571 /* The HCI transport will segment the buffers. */
3572 if (p_buf->len > acl_data_size) {
3573 UINT16_TO_STREAM (p, acl_data_size);
3574 } else {
3575 UINT16_TO_STREAM (p, p_buf->len);
3576 }
3577 } /* (BLE_INCLUDED == TRUE) */
3578 else
3579 #endif
3580 {
3581 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
3582 if ( (((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) == L2CAP_FLUSHABLE_CH_BASED) && (p_ccb->is_flushable))
3583 || ((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) == L2CAP_FLUSHABLE_PKT) ) {
3584 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3585 } else {
3586 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | l2cb.non_flushable_pbf);
3587 }
3588 #else
3589 UINT16_TO_STREAM (p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3590 #endif
3591
3592 uint16_t acl_data_size = controller_get_interface()->get_acl_data_size_classic();
3593 /* The HCI transport will segment the buffers. */
3594 if (p_buf->len > acl_data_size) {
3595 UINT16_TO_STREAM (p, acl_data_size);
3596 } else {
3597 UINT16_TO_STREAM (p, p_buf->len);
3598 }
3599 }
3600 p_buf->offset -= HCI_DATA_PREAMBLE_SIZE;
3601 p_buf->len += HCI_DATA_PREAMBLE_SIZE;
3602 }
3603
3604 /******************************************************************************
3605 **
3606 ** Function l2cu_check_channel_congestion
3607 **
3608 ** Description check if any change in congestion status
3609 **
3610 ** Returns None
3611 **
3612 *******************************************************************************/
3613 void l2cu_check_channel_congestion (tL2C_CCB *p_ccb)
3614 {
3615 size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q);
3616
3617 #if (L2CAP_UCD_INCLUDED == TRUE)
3618 if ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3619 q_count += fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q);
3620 }
3621 #endif
3622 /* If the CCB queue limit is subject to a quota, check for congestion */
3623 /* if this channel has outgoing traffic */
3624 if (p_ccb->buff_quota != 0) {
3625 /* If this channel was congested */
3626 if ( p_ccb->cong_sent ) {
3627 /* If the channel is not congested now, tell the app */
3628 if (q_count <= (p_ccb->buff_quota / 2)) {
3629 p_ccb->cong_sent = FALSE;
3630 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3631 L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (FALSE), CID: 0x%04x xmit_hold_q.count: %u buff_quota: %u",
3632 p_ccb->local_cid, q_count, p_ccb->buff_quota);
3633
3634 /* Prevent recursive calling */
3635 l2cb.is_cong_cback_context = TRUE;
3636 (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, FALSE);
3637 l2cb.is_cong_cback_context = FALSE;
3638 }
3639 #if (L2CAP_UCD_INCLUDED == TRUE)
3640 else if ( p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3641 if ( p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ) {
3642 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCD CongestionStatus_Cb (FALSE), SecPendingQ:%u,XmitQ:%u,Quota:%u",
3643 fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3644 fixed_queue_length(p_ccb->xmit_hold_q),
3645 p_ccb->buff_quota);
3646 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( p_ccb->p_lcb->remote_bd_addr, FALSE );
3647 }
3648 }
3649 #endif
3650 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3651 else {
3652 UINT8 xx;
3653 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx ++) {
3654 if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3655 if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL) {
3656 (* l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr, FALSE);
3657 }
3658 break;
3659 }
3660 }
3661 }
3662 #endif
3663 }
3664 } else {
3665 tL2C_LCB *p_lcb = p_ccb->p_lcb;
3666 /* If this channel was not congested but it is congested now, tell the app */
3667 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)) {
3668 p_ccb->cong_sent = TRUE;
3669 if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3670 L2CAP_TRACE_DEBUG ("L2CAP - Calling CongestionStatus_Cb (TRUE),CID:0x%04x,XmitQ:%u,Quota:%u",
3671 p_ccb->local_cid, q_count, p_ccb->buff_quota);
3672
3673 (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, TRUE);
3674 }
3675 #if (L2CAP_UCD_INCLUDED == TRUE)
3676 else if ( p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ) {
3677 if ( p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ) {
3678 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCD CongestionStatus_Cb (TRUE), SecPendingQ:%u,XmitQ:%u,Quota:%u",
3679 fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3680 fixed_queue_length(p_ccb->xmit_hold_q),
3681 p_ccb->buff_quota);
3682 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( p_ccb->p_lcb->remote_bd_addr, TRUE );
3683 }
3684 }
3685 #endif
3686 #if (L2CAP_NUM_FIXED_CHNLS > 0)
3687 else {
3688 UINT8 xx;
3689 for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx ++) {
3690 if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3691 if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL) {
3692 (* l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(p_ccb->p_lcb->remote_bd_addr, TRUE);
3693 }
3694 break;
3695 }
3696 }
3697 }
3698 #endif
3699 }
3700 }
3701 }
3702 }
3703