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