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