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