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