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