1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
|
/******************************************************************************
*
* Copyright (C) 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Changes from Qualcomm Innovation Center are provided under the following license:
*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
*
******************************************************************************/
/******************************************************************************
*
* This file contains L2CAP internal definitions
*
******************************************************************************/
#ifndef L2C_INT_H
#define L2C_INT_H
#include <stdbool.h>
#include <list>
#include <map>
#include "bt_common.h"
#include "btm_api.h"
#include "btm_ble_api.h"
#include "l2c_api.h"
#include "l2cdefs.h"
#include "osi/include/alarm.h"
#include "osi/include/fixed_queue.h"
#include "osi/include/list.h"
#define L2CAP_MIN_MTU 48 /* Minimum acceptable MTU is 48 bytes */
#define MAX_ACTIVE_AVDT_CONN 5
/* LE credit based L2CAP connection parameters */
constexpr uint16_t L2CAP_LE_MIN_MTU = 23; // Minimum SDU size
constexpr uint16_t L2CAP_LE_MIN_MPS = 23;
constexpr uint16_t L2CAP_LE_MAX_MPS = 65533;
constexpr uint16_t L2CAP_LE_CREDIT_MAX = 65535;
/* L2CAP Enhanced credit based flow control mode config params */
constexpr uint16_t L2CAP_COC_MIN_MTU = 64; // Minimum SDU size
constexpr uint16_t L2CAP_COC_MIN_MPS = 64;
constexpr uint16_t L2CAP_COC_MAX_MPS = 65533;
// This is initial amount of credits we send, and amount to which we increase
// credits once they fall below threshold in LE Credit based flow control mode
constexpr uint16_t L2CAP_LE_CREDIT_DEFAULT = 0xffff;
// This is initial amount of credits we send, and amount to which we increase
// credits once they fall below threshold in Enhanced Credit based flow control mode.
constexpr uint16_t L2CAP_COC_CREDIT_DEFAULT = 0x00ff;
// If credit count on remote fall below this value, we send back credits to
// reach default value.
constexpr uint16_t L2CAP_LE_CREDIT_THRESHOLD = 0x0040;
static_assert(L2CAP_LE_CREDIT_THRESHOLD < L2CAP_LE_CREDIT_DEFAULT,
"Threshold must be smaller then default credits");
/*
* Timeout values (in milliseconds).
*/
#define L2CAP_LINK_ROLE_SWITCH_TIMEOUT_MS (10 * 1000) /* 10 seconds */
#define L2CAP_LINK_CONNECT_TIMEOUT_MS (20 * 1000) /* 20 seconds */
#define L2CAP_LINK_CONNECT_EXT_TIMEOUT_MS (120 * 1000) /* 120 seconds */
#define L2CAP_ECHO_RSP_TIMEOUT_MS (30 * 1000) /* 30 seconds */
#define L2CAP_LINK_FLOW_CONTROL_TIMEOUT_MS (2 * 1000) /* 2 seconds */
#define L2CAP_LINK_DISCONNECT_TIMEOUT_MS (30 * 1000) /* 30 seconds */
#define L2CAP_CHNL_CONNECT_TIMEOUT_MS (20 * 1000) /* 20 seconds */
#define L2CAP_CHNL_CONNECT_EXT_TIMEOUT_MS (120 * 1000) /* 120 seconds */
#define L2CAP_CHNL_CFG_TIMEOUT_MS (30 * 1000) /* 30 seconds */
#define L2CAP_CHNL_DISCONNECT_TIMEOUT_MS (10 * 1000) /* 10 seconds */
#define L2CAP_DELAY_CHECK_SM4_TIMEOUT_MS (2 * 1000) /* 2 seconds */
#define L2CAP_WAIT_INFO_RSP_TIMEOUT_MS (3 * 1000) /* 3 seconds */
#define L2CAP_BLE_LINK_CONNECT_TIMEOUT_MS (30 * 1000) /* 30 seconds */
#define L2CAP_FCR_ACK_TIMEOUT_MS 200 /* 200 milliseconds */
#define L2CAP_FCR_RX_BUF_MONITORING_TIMEOUT_MS 500 /* 500 milliseconds */
/* Define the possible L2CAP channel states. The names of
* the states may seem a bit strange, but they are taken from
* the Bluetooth specification.
*/
typedef enum {
CST_CLOSED, /* Channel is in closed state */
CST_ORIG_W4_SEC_COMP, /* Originator waits security clearence */
CST_TERM_W4_SEC_COMP, /* Acceptor waits security clearence */
CST_W4_L2CAP_CONNECT_RSP, /* Waiting for peer conenct response */
CST_W4_L2CA_CONNECT_RSP, /* Waiting for upper layer connect rsp */
CST_CONFIG, /* Negotiating configuration */
CST_OPEN, /* Data transfer state */
CST_W4_L2CAP_DISCONNECT_RSP, /* Waiting for peer disconnect rsp */
CST_W4_L2CA_DISCONNECT_RSP /* Waiting for upper layer disc rsp */
} tL2C_CHNL_STATE;
/* Define the possible L2CAP link states
*/
typedef enum {
LST_DISCONNECTED,
LST_CONNECT_HOLDING,
LST_CONNECTING_WAIT_SWITCH,
LST_CONNECTING,
LST_CONNECTED,
LST_DISCONNECTING
} tL2C_LINK_STATE;
/* Define input events to the L2CAP link and channel state machines. The names
* of the events may seem a bit strange, but they are taken from
* the Bluetooth specification.
*/
/* Lower layer */
#define L2CEVT_LP_CONNECT_CFM 0 /* connect confirm */
#define L2CEVT_LP_CONNECT_CFM_NEG 1 /* connect confirm (failed) */
#define L2CEVT_LP_CONNECT_IND 2 /* connect indication */
#define L2CEVT_LP_DISCONNECT_IND 3 /* disconnect indication */
#define L2CEVT_LP_QOS_CFM 4 /* QOS confirmation */
#define L2CEVT_LP_QOS_CFM_NEG 5 /* QOS confirmation (failed)*/
#define L2CEVT_LP_QOS_VIOLATION_IND 6 /* QOS violation indication */
/* Security */
#define L2CEVT_SEC_COMP 7 /* cleared successfully */
#define L2CEVT_SEC_COMP_NEG 8 /* procedure failed */
/* Peer connection */
#define L2CEVT_L2CAP_CONNECT_REQ 10 /* request */
#define L2CEVT_L2CAP_CONNECT_RSP 11 /* response */
#define L2CEVT_L2CAP_CONNECT_RSP_PND 12 /* response pending */
#define L2CEVT_L2CAP_CONNECT_RSP_NEG 13 /* response (failed) */
/* Peer configuration */
#define L2CEVT_L2CAP_CONFIG_REQ 14 /* request */
#define L2CEVT_L2CAP_CONFIG_RSP 15 /* response */
#define L2CEVT_L2CAP_CONFIG_RSP_NEG 16 /* response (failed) */
#define L2CEVT_L2CAP_DISCONNECT_REQ 17 /* Peer disconnect request */
#define L2CEVT_L2CAP_DISCONNECT_RSP 18 /* Peer disconnect response */
#define L2CEVT_L2CAP_INFO_RSP 19 /* Peer information response */
#define L2CEVT_L2CAP_DATA 20 /* Peer data */
/* Upper layer */
#define L2CEVT_L2CA_CONNECT_REQ 21 /* connect request */
#define L2CEVT_L2CA_CONNECT_RSP 22 /* connect response */
#define L2CEVT_L2CA_CONNECT_RSP_NEG 23 /* connect response (failed)*/
#define L2CEVT_L2CA_CONFIG_REQ 24 /* config request */
#define L2CEVT_L2CA_CONFIG_RSP 25 /* config response */
#define L2CEVT_L2CA_CONFIG_RSP_NEG 26 /* config response (failed) */
#define L2CEVT_L2CA_DISCONNECT_REQ 27 /* disconnect request */
#define L2CEVT_L2CA_DISCONNECT_RSP 28 /* disconnect response */
#define L2CEVT_L2CA_DATA_READ 29 /* data read */
#define L2CEVT_L2CA_DATA_WRITE 30 /* data write */
#define L2CEVT_L2CA_FLUSH_REQ 31 /* flush */
#define L2CEVT_TIMEOUT 32 /* Timeout */
#define L2CEVT_SEC_RE_SEND_CMD 33 /* btm_sec has enough info to proceed */
#define L2CEVT_ACK_TIMEOUT 34 /* RR delay timeout */
#define L2CEVT_L2CA_SEND_LE_FLOW_CONTROL_CREDIT \
35 /* Upper layer credit packet \
*/
#define L2CEVT_L2CAP_RECV_LE_FLOW_CONTROL_CREDIT 36 /* Peer credit packet */
/* Upper Layer Events in ECFC mode */
#define L2CEVT_L2CA_COC_CONNECT_REQ 37
#define L2CEVT_L2CA_COC_CONNECT_RSP 38
#define L2CEVT_L2CA_COC_CONNECT_NEG_RSP 39
#define L2CEVT_L2CA_COC_RECONFIG_REQ 40
#define L2CEVT_L2CA_COC_RECONFIG_RSP 41
/* Upper Layer Credit indication event in ECFC Mode */
#define L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT 42
/* Peer Connection Events in ECFC Mode */
#define L2CEVT_L2CAP_COC_CONNECT_REQ 43
#define L2CEVT_L2CAP_COC_CONNECT_RSP 44
#define L2CEVT_L2CAP_COC_CONNECT_NEG_RSP 45
/* Peer Reconfiguration Events in ECFC Mode */
#define L2CEVT_L2CAP_COC_RECONFIG_REQ 46
#define L2CEVT_L2CAP_COC_RECONFIG_RSP 47
/* Peer Credit indication event in ECFC Mode */
#define L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT 48
/* Constants for LE Dynamic PSM values */
#define L2CAP_COC_DYNAMIC_PSM_START 0x0080
#define L2CAP_COC_DYNAMIC_PSM_END 0x00FF
#define L2CAP_COC_DYNAMIC_PSM_RANGE \
(L2CAP_COC_DYNAMIC_PSM_END - L2CAP_COC_DYNAMIC_PSM_START + 1)
/* Bitmask to skip over Broadcom feature reserved (ID) to avoid sending two
successive ID values, '0' id only or both */
#define L2CAP_ADJ_BRCM_ID 0x1
#define L2CAP_ADJ_ZERO_ID 0x2
#define L2CAP_ADJ_ID 0x3
/* Return values for l2cu_process_peer_cfg_req() */
#define L2CAP_PEER_CFG_UNACCEPTABLE 0
#define L2CAP_PEER_CFG_OK 1
#define L2CAP_PEER_CFG_DISCONNECT 2
/* eL2CAP option constants */
/* Min retransmission timeout if no flush timeout or PBF */
#define L2CAP_MIN_RETRANS_TOUT 2000
/* Min monitor timeout if no flush timeout or PBF */
#define L2CAP_MIN_MONITOR_TOUT 12000
#define L2CAP_MAX_FCR_CFG_TRIES 2 /* Config attempts before disconnecting */
//errata id = 14605
#define CONNECTION_PENDING 1
#define CONNECTION_PENDING_RESET 0
#define L2CAP_AUTHORIZATION_PENDING 1
#define L2CAP_AUTHORIZATION_PENDING_RESET 0
typedef uint8_t tL2C_BLE_FIXED_CHNLS_MASK;
typedef struct {
uint8_t next_tx_seq; /* Next sequence number to be Tx'ed */
uint8_t last_rx_ack; /* Last sequence number ack'ed by the peer */
uint8_t next_seq_expected; /* Next peer sequence number expected */
uint8_t last_ack_sent; /* Last peer sequence number ack'ed */
uint8_t num_tries; /* Number of retries to send a packet */
uint8_t max_held_acks; /* Max acks we can hold before sending */
bool remote_busy; /* true if peer has flowed us off */
bool local_busy; /* true if we have flowed off the peer */
bool rej_sent; /* Reject was sent */
bool srej_sent; /* Selective Reject was sent */
bool wait_ack; /* Transmitter is waiting ack (poll sent) */
bool rej_after_srej; /* Send a REJ when SREJ clears */
bool send_f_rsp; /* We need to send an F-bit response */
uint16_t rx_sdu_len; /* Length of the SDU being received */
BT_HDR* p_rx_sdu; /* Buffer holding the SDU being received */
fixed_queue_t*
waiting_for_ack_q; /* Buffers sent and waiting for peer to ack */
fixed_queue_t* srej_rcv_hold_q; /* Buffers rcvd but held pending SREJ rsp */
fixed_queue_t* retrans_q; /* Buffers being retransmitted */
alarm_t* ack_timer; /* Timer delaying RR */
alarm_t* mon_retrans_timer; /* Timer Monitor or Retransmission */
#if (L2CAP_ERTM_STATS == TRUE)
uint32_t connect_tick_count; /* Time channel was established */
uint32_t ertm_pkt_counts[2]; /* Packets sent and received */
uint32_t ertm_byte_counts[2]; /* Bytes sent and received */
uint32_t s_frames_sent[4]; /* S-frames sent (RR, REJ, RNR, SREJ) */
uint32_t s_frames_rcvd[4]; /* S-frames rcvd (RR, REJ, RNR, SREJ) */
uint32_t xmit_window_closed; /* # of times the xmit window was closed */
uint32_t controller_idle; /* # of times less than 2 packets in controller */
/* when the xmit window was closed */
uint32_t pkts_retransmitted; /* # of packets that were retransmitted */
uint32_t retrans_touts; /* # of retransmission timouts */
uint32_t xmit_ack_touts; /* # of xmit ack timouts */
#define L2CAP_ERTM_STATS_NUM_AVG 10
#define L2CAP_ERTM_STATS_AVG_NUM_SAMPLES 100
uint32_t ack_delay_avg_count;
uint32_t ack_delay_avg_index;
uint32_t throughput_start;
uint32_t throughput[L2CAP_ERTM_STATS_NUM_AVG];
uint32_t ack_delay_avg[L2CAP_ERTM_STATS_NUM_AVG];
uint32_t ack_delay_min[L2CAP_ERTM_STATS_NUM_AVG];
uint32_t ack_delay_max[L2CAP_ERTM_STATS_NUM_AVG];
uint32_t ack_q_count_avg[L2CAP_ERTM_STATS_NUM_AVG];
uint32_t ack_q_count_min[L2CAP_ERTM_STATS_NUM_AVG];
uint32_t ack_q_count_max[L2CAP_ERTM_STATS_NUM_AVG];
#endif
} tL2C_FCRB;
/* Define a registration control block. Every application (e.g. RFCOMM, SDP,
* TCS etc) that registers with L2CAP is assigned one of these.
*/
#if (L2CAP_UCD_INCLUDED == TRUE)
#define L2C_UCD_RCB_ID 0x00
#define L2C_UCD_STATE_UNUSED 0x00
#define L2C_UCD_STATE_W4_DATA 0x01
#define L2C_UCD_STATE_W4_RECEPTION 0x02
#define L2C_UCD_STATE_W4_MTU 0x04
typedef struct {
uint8_t state;
tL2CAP_UCD_CB_INFO cb_info;
} tL2C_UCD_REG;
#endif
typedef struct {
bool in_use;
bool log_packets;
uint16_t psm;
uint16_t real_psm; /* This may be a dummy RCB for an o/b connection but */
/* this is the real PSM that we need to connect to */
#if (L2CAP_UCD_INCLUDED == TRUE)
tL2C_UCD_REG ucd;
#endif
tL2CAP_APPL_INFO api;
tL2CAP_COC_APPL_INFO coc_api;
} tL2C_RCB;
#ifndef L2CAP_CBB_DEFAULT_DATA_RATE_BUFF_QUOTA
#define L2CAP_CBB_DEFAULT_DATA_RATE_BUFF_QUOTA 10
#endif
typedef void(tL2CAP_SEC_CBACK)(const RawAddress& bd_addr,
tBT_TRANSPORT trasnport, void* p_ref_data,
tBTM_STATUS result);
typedef struct {
uint16_t psm;
tBT_TRANSPORT transport;
bool is_originator;
tL2CAP_SEC_CBACK* p_callback;
void* p_ref_data;
} tL2CAP_SEC_DATA;
typedef struct {
uint8_t num_coc_chnls;
uint8_t ecfc_conn_result;
uint8_t requested_ecfc_chnls;
#define L2CAP_ECFC_LINK_CONNECT_CFM_CB 0x1
#define L2CAP_ECFC_SEC_PENDING_CB 0x2
#define L2CAP_ECFC_INFO_RSP_EVT 0x4
#define L2CAP_ECFC_PROCESS_DLE_EVT 0x8
uint8_t ecfc_grp_status;
uint16_t ecfc_cids_group[L2C_MAX_ECFC_CHNLS_PER_CONN];
//TODO if extra array is concern then allocate and free the below array
uint16_t peer_rsp_cids[L2C_MAX_ECFC_CHNLS_PER_CONN];
uint64_t disc_pending;
alarm_t* ecfc_conn_alarm;
//errata id = 14605
uint64_t connection_pending;
uint64_t authorization_pending;
} tL2C_coc_cmd_info;
/* This structure contains information needed to handle ECFC reconfig Request */
typedef struct {
tL2CAP_COC_CFG_INFO cfg_params;
uint16_t result;
alarm_t* l2c_cfg_timer = NULL;
tL2CAP_COC_CHMAP_INFO chnl_info;
uint8_t trans_id;
} tL2C_CFG_REQ_PARAM;
/* Structure used to maintain incoming l2cap packets in Enhanced credit
based flow control mode */
typedef struct {
bool is_dequeued = FALSE; /* flag to check if upper layer is dequeing data
or not after threshold credit limit is reached.*/
uint16_t rx_data_q_size; /* size of rcv_data_q */
fixed_queue_t* rcv_data_q; /* l2cap incoming data queue */
alarm_t* l2c_coc_credit_mon_timer; /* CCB Timer Entry */
} tL2CAP_COC_RX_BUF;
/* Define a channel control block (CCB). There may be many channel control
* blocks between the same two Bluetooth devices (i.e. on the same link).
* Each CCB has unique local and remote CIDs. All channel control blocks on
* the same physical link and are chained together.
*/
typedef struct t_l2c_ccb {
bool in_use; /* true when in use, false when not */
tL2C_CHNL_STATE chnl_state; /* Channel state */
tL2CAP_COC_CFG_INFO
local_conn_cfg; /* Our config for ble conn oriented channel */
tL2CAP_COC_CFG_INFO
peer_conn_cfg; /* Peer device config ble conn oriented channel */
bool is_first_seg; /* Dtermine whether the received packet is the first
segment or not */
BT_HDR* ble_sdu; /* Buffer for storing unassembled sdu*/
uint16_t ble_sdu_length; /* Length of unassembled sdu length*/
struct t_l2c_ccb* p_next_ccb; /* Next CCB in the chain */
struct t_l2c_ccb* p_prev_ccb; /* Previous CCB in the chain */
struct t_l2c_linkcb* p_lcb; /* Link this CCB is assigned to */
uint16_t local_cid; /* Local CID */
uint16_t remote_cid; /* Remote CID */
alarm_t* l2c_ccb_timer; /* CCB Timer Entry */
tL2C_RCB* p_rcb; /* Registration CB for this Channel */
bool should_free_rcb; /* True if RCB was allocated on the heap */
#define IB_CFG_DONE 0x01
#define OB_CFG_DONE 0x02
#define RECONFIG_FLAG 0x04 /* True after initial configuration */
#define CFG_DONE_MASK (IB_CFG_DONE | OB_CFG_DONE)
uint8_t config_done; /* Configuration flag word */
uint8_t local_id; /* Transaction ID for local trans */
uint8_t remote_id; /* Transaction ID for local */
#define CCB_FLAG_NO_RETRY 0x01 /* no more retry */
#define CCB_FLAG_SENT_PENDING 0x02 /* already sent pending response */
uint8_t flags;
tL2CAP_CFG_INFO our_cfg; /* Our saved configuration options */
tL2CAP_CH_CFG_BITS peer_cfg_bits; /* Store what peer wants to configure */
tL2CAP_CFG_INFO peer_cfg; /* Peer's saved configuration options */
fixed_queue_t* xmit_hold_q; /* Transmit data hold queue */
bool cong_sent; /* Set when congested status sent */
uint16_t buff_quota; /* Buffer quota before sending congestion */
tL2CAP_CHNL_PRIORITY ccb_priority; /* Channel priority */
tL2CAP_CHNL_DATA_RATE tx_data_rate; /* Channel Tx data rate */
tL2CAP_CHNL_DATA_RATE rx_data_rate; /* Channel Rx data rate */
/* Fields used for eL2CAP */
tL2CAP_ERTM_INFO ertm_info;
tL2C_FCRB fcrb;
uint16_t tx_mps; /* TX MPS adjusted based on current controller */
uint16_t max_rx_mtu;
uint8_t fcr_cfg_tries; /* Max number of negotiation attempts */
bool peer_cfg_already_rejected; /* If mode rejected once, set to true */
bool out_cfg_fcr_present; /* true if cfg response shoulkd include fcr options
*/
#define L2CAP_CFG_FCS_OUR 0x01 /* Our desired config FCS option */
#define L2CAP_CFG_FCS_PEER 0x02 /* Peer's desired config FCS option */
#define L2CAP_BYPASS_FCS (L2CAP_CFG_FCS_OUR | L2CAP_CFG_FCS_PEER)
uint8_t bypass_fcs;
#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
bool is_flushable; /* true if channel is flushable */
#endif
#if (L2CAP_NUM_FIXED_CHNLS > 0 || L2CAP_UCD_INCLUDED == TRUE)
uint16_t fixed_chnl_idle_tout; /* Idle timeout to use for the fixed channel */
#endif
uint16_t tx_data_len;
/* Number of frames that the remote can send to us (credit count in
* remote). Valid only for CoC */
uint16_t remote_credit_count;
// Below variable are used in ECFC mode only.
tL2C_coc_cmd_info coc_cmd_info;
tL2C_CFG_REQ_PARAM*
pending_out_cfg; /* pending outgoing config params be applied after
getting reconfig response from peer device*/
tL2C_CFG_REQ_PARAM*
pending_inc_cfg; /* pending incoming config params be applied after
getting reconfig response from upper layer*/
tL2CAP_COC_RX_BUF rx_buf; /* buffer to store incoming l2cap packets in ECFC mode*/
} tL2C_CCB;
/***********************************************************************
* Define a queue of linked CCBs.
*/
typedef struct {
tL2C_CCB* p_first_ccb; /* The first channel in this queue */
tL2C_CCB* p_last_ccb; /* The last channel in this queue */
} tL2C_CCB_Q;
#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
/* Round-Robin service for the same priority channels */
#define L2CAP_NUM_CHNL_PRIORITY \
3 /* Total number of priority group (high, medium, low)*/
#define L2CAP_CHNL_PRIORITY_WEIGHT \
5 /* weight per priority for burst transmission quota */
#define L2CAP_GET_PRIORITY_QUOTA(pri) \
((L2CAP_NUM_CHNL_PRIORITY - (pri)) * L2CAP_CHNL_PRIORITY_WEIGHT)
/* CCBs within the same LCB are served in round robin with priority It will make
* sure that low priority channel (for example, HF signaling on RFCOMM) can be
* sent to the headset even if higher priority channel (for example, AV media
* channel) is congested.
*/
typedef struct {
tL2C_CCB* p_serve_ccb; /* current serving ccb within priority group */
tL2C_CCB* p_first_ccb; /* first ccb of priority group */
uint8_t num_ccb; /* number of channels in priority group */
uint8_t quota; /* burst transmission quota */
} tL2C_RR_SERV;
#endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
/* Define a link control block. There is one link control block between
* this device and any other device (i.e. BD ADDR).
*/
typedef struct t_l2c_linkcb {
bool in_use; /* true when in use, false when not */
tL2C_LINK_STATE link_state;
alarm_t* l2c_lcb_timer; /* Timer entry for timeout evt */
uint16_t handle; /* The handle used with LM */
tL2C_CCB_Q ccb_queue; /* Queue of CCBs on this LCB */
tL2C_CCB* p_pending_ccb; /* ccb of waiting channel during link disconnect */
alarm_t* info_resp_timer; /* Timer entry for info resp timeout evt */
RawAddress remote_bd_addr; /* The BD address of the remote */
uint8_t link_role; /* Master or slave */
uint8_t id;
uint8_t cur_echo_id; /* Current id value for echo request */
tL2CA_ECHO_RSP_CB* p_echo_rsp_cb; /* Echo response callback */
uint16_t idle_timeout; /* Idle timeout */
bool is_bonding; /* True - link active only for bonding */
uint16_t link_flush_tout; /* Flush timeout used */
uint16_t link_xmit_quota; /* Num outstanding pkts allowed */
uint16_t sent_not_acked; /* Num packets sent but not acked */
bool partial_segment_being_sent; /* Set true when a partial segment */
/* is being sent. */
bool w4_info_rsp; /* true when info request is active */
uint8_t info_rx_bits; /* set 1 if received info type */
uint32_t peer_ext_fea; /* Peer's extended features mask */
list_t* link_xmit_data_q; /* Link transmit data buffer queue */
uint8_t peer_chnl_mask[L2CAP_FIXED_CHNL_ARRAY_SIZE];
#if (L2CAP_UCD_INCLUDED == TRUE)
uint16_t ucd_mtu; /* peer MTU on UCD */
fixed_queue_t*
ucd_out_sec_pending_q; /* Security pending outgoing UCD packet */
fixed_queue_t*
ucd_in_sec_pending_q; /* Security pending incoming UCD packet */
#endif
BT_HDR* p_hcit_rcv_acl; /* Current HCIT ACL buf being rcvd */
uint16_t idle_timeout_sv; /* Save current Idle timeout */
uint8_t acl_priority; /* L2C_PRIORITY_NORMAL or L2C_PRIORITY_HIGH */
tL2CA_NOCP_CB* p_nocp_cb; /* Num Cmpl pkts callback */
#if (L2CAP_NUM_FIXED_CHNLS > 0)
tL2C_CCB* p_fixed_ccbs[L2CAP_NUM_FIXED_CHNLS];
uint16_t disc_reason;
#endif
tBT_TRANSPORT transport;
uint8_t initiating_phys; // LE PHY used for connection initiation
tBLE_ADDR_TYPE ble_addr_type;
uint16_t tx_data_len; /* tx data length used in data length extension */
fixed_queue_t* le_sec_pending_q; /* LE coc channels waiting for security check
completion */
uint8_t sec_act;
#define L2C_BLE_CONN_UPDATE_DISABLE \
0x1 /* disable update connection parameters */
#define L2C_BLE_NEW_CONN_PARAM 0x2 /* new connection parameter to be set */
#define L2C_BLE_UPDATE_PENDING \
0x4 /* waiting for connection update finished \
*/
#define L2C_BLE_NOT_DEFAULT_PARAM \
0x8 /* not using default connection parameters */
uint8_t conn_update_mask;
uint16_t min_interval; /* parameters as requested by peripheral */
uint16_t max_interval;
uint16_t latency;
uint16_t timeout;
uint16_t min_ce_len;
uint16_t max_ce_len;
#define L2C_BLE_SUBRATE_REQ_DISABLE \
0x1 /* disable subrate req */
#define L2C_BLE_NEW_SUBRATE_PARAM 0x2 /* new subrate req parameter to be set */
#define L2C_BLE_SUBRATE_REQ_PENDING \
0x4 /* waiting for subrate change to be completed \
*/
/* subrate req params */
uint16_t subrate_min;
uint16_t subrate_max;
uint16_t max_latency;
uint16_t cont_num;
uint16_t supervision_tout;
uint8_t subrate_req_mask;
#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
/* each priority group is limited burst transmission */
/* round robin service for the same priority channels */
tL2C_RR_SERV rr_serv[L2CAP_NUM_CHNL_PRIORITY];
uint8_t rr_pri; /* current serving priority group */
#endif
} tL2C_LCB;
/* Define the L2CAP control structure
*/
typedef struct {
uint8_t l2cap_trace_level;
uint16_t controller_xmit_window; /* Total ACL window for all links */
uint16_t round_robin_quota; /* Round-robin link quota */
uint16_t round_robin_unacked; /* Round-robin unacked */
bool check_round_robin; /* Do a round robin check */
bool is_cong_cback_context;
tL2C_LCB lcb_pool[MAX_L2CAP_LINKS]; /* Link Control Block pool */
tL2C_CCB ccb_pool[MAX_L2CAP_CHANNELS]; /* Channel Control Block pool */
tL2C_RCB rcb_pool[MAX_L2CAP_CLIENTS]; /* Registration info pool */
tL2C_CCB* p_free_ccb_first; /* Pointer to first free CCB */
tL2C_CCB* p_free_ccb_last; /* Pointer to last free CCB */
uint8_t
desire_role; /* desire to be master/slave when accepting a connection */
bool disallow_switch; /* false, to allow switch at create conn */
uint16_t num_lm_acl_bufs; /* # of ACL buffers on controller */
uint16_t idle_timeout; /* Idle timeout */
list_t* rcv_pending_q; /* Recv pending queue */
alarm_t* receive_hold_timer; /* Timer entry for rcv hold */
tL2C_LCB* p_cur_hcit_lcb; /* Current HCI Transport buffer */
uint16_t num_links_active; /* Number of links active */
#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
uint16_t non_flushable_pbf; /* L2CAP_PKT_START_NON_FLUSHABLE if controller
supports */
/* Otherwise, L2CAP_PKT_START */
bool is_flush_active; /* true if an HCI_Enhanced_Flush has been sent */
#endif
#if (L2CAP_CONFORMANCE_TESTING == TRUE)
uint32_t test_info_resp; /* Conformance testing needs a dynamic response */
#endif
#if (L2CAP_NUM_FIXED_CHNLS > 0)
tL2CAP_FIXED_CHNL_REG
fixed_reg[L2CAP_NUM_FIXED_CHNLS]; /* Reg info for fixed channels */
#endif
uint16_t num_ble_links_active; /* Number of LE links active */
uint16_t controller_le_xmit_window; /* Total ACL window for all links */
tL2C_BLE_FIXED_CHNLS_MASK l2c_ble_fixed_chnls_mask; // LE fixed channels mask
uint16_t num_lm_ble_bufs; /* # of ACL buffers on controller */
uint16_t ble_round_robin_quota; /* Round-robin link quota */
uint16_t ble_round_robin_unacked; /* Round-robin unacked */
bool ble_check_round_robin; /* Do a round robin check */
tL2C_RCB coc_rcb_pool[L2CAP_COC_MAX_CLIENTS]; /* Registration info pool */
tL2CA_ECHO_DATA_CB* p_echo_data_cb; /* Echo data callback */
#if (L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE == TRUE)
uint16_t high_pri_min_xmit_quota; /* Minimum number of ACL credit for high
priority link */
#endif /* (L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE == TRUE) */
uint16_t dyn_psm;
uint16_t coc_dyn_psm; /* Next LE dynamic PSM value to try to assign */
bool coc_dyn_psm_assigned[L2CAP_COC_DYNAMIC_PSM_RANGE]; /* Table of assigned LE PSM */
uint8_t cert_failure; /*Insufficient Enc case for certification */
} tL2C_CB;
/* Define a structure that contains the information about a connection.
* This structure is used to pass between functions, and not all the
* fields will always be filled in.
*/
typedef struct {
RawAddress bd_addr; /* Remote BD address */
uint8_t status; /* Connection status */
uint16_t psm; /* PSM of the connection */
uint16_t l2cap_result; /* L2CAP result */
uint16_t l2cap_status; /* L2CAP status */
uint16_t remote_cid; /* Remote CID */
} tL2C_CONN_INFO;
typedef struct {
bool is_active; /* is channel active */
uint16_t local_cid; /* Remote CID */
tL2C_CCB *p_ccb; /* CCB */
} tL2C_AVDT_CHANNEL_INFO;
typedef void(tL2C_FCR_MGMT_EVT_HDLR)(uint8_t, tL2C_CCB*);
/* Necessary info for postponed TX completion callback
*/
typedef struct {
uint16_t local_cid;
uint16_t num_sdu;
tL2CA_TX_COMPLETE_CB* cb;
} tL2C_TX_COMPLETE_CB_INFO;
/* The offset in a buffer that L2CAP will use when building commands.
*/
#define L2CAP_SEND_CMD_OFFSET 0
/* Number of ACL buffers to use for high priority channel
*/
#if (L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE == FALSE)
#define L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A (L2CAP_HIGH_PRI_MIN_XMIT_QUOTA)
#else
#define L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A (l2cb.high_pri_min_xmit_quota)
#endif
/* L2CAP global data
***********************************
*/
extern tL2C_CB l2cb;
/* Functions provided by l2c_main.cc
***********************************
*/
void l2c_init(void);
void l2c_free(void);
extern void l2c_receive_hold_timer_timeout(void* data);
extern void l2c_ccb_timer_timeout(void* data);
extern void l2c_lcb_timer_timeout(void* data);
extern void l2c_fcrb_ack_timer_timeout(void* data);
extern uint8_t l2c_data_write(uint16_t cid, BT_HDR* p_data, uint16_t flag);
extern void l2c_rcv_acl_data(BT_HDR* p_msg);
extern void l2c_process_held_packets(bool timed_out);
extern void l2c_rcfg_timer_timeout(void* data);
/* Functions provided by l2c_utils.cc
***********************************
*/
extern bool l2cu_can_allocate_lcb(void);
extern tL2C_LCB* l2cu_allocate_lcb(const RawAddress& p_bd_addr, bool is_bonding,
tBT_TRANSPORT transport);
extern bool l2cu_start_post_bond_timer(uint16_t handle);
extern void l2cu_release_lcb(tL2C_LCB* p_lcb);
extern tL2C_LCB* l2cu_find_lcb_by_bd_addr(const RawAddress& p_bd_addr,
tBT_TRANSPORT transport);
extern tL2C_LCB* l2cu_find_lcb_by_handle(uint16_t handle);
extern void l2cu_update_lcb_4_bonding(const RawAddress& p_bd_addr,
bool is_bonding);
extern uint8_t l2cu_get_conn_role(tL2C_LCB* p_this_lcb);
extern bool l2cu_set_acl_priority(const RawAddress& bd_addr, uint8_t priority,
bool reset_after_rs);
extern void l2cu_enqueue_ccb(tL2C_CCB* p_ccb);
extern void l2cu_dequeue_ccb(tL2C_CCB* p_ccb);
extern void l2cu_change_pri_ccb(tL2C_CCB* p_ccb, tL2CAP_CHNL_PRIORITY priority);
extern tL2C_CCB* l2cu_allocate_ccb(tL2C_LCB* p_lcb, uint16_t cid);
extern void l2cu_release_ccb(tL2C_CCB* p_ccb);
extern tL2C_CCB* l2cu_find_ccb_by_cid(tL2C_LCB* p_lcb, uint16_t local_cid);
extern tL2C_CCB* l2cu_find_ccb_by_remote_cid(tL2C_LCB* p_lcb,
uint16_t remote_cid);
extern void l2cu_adj_id(tL2C_LCB* p_lcb, uint8_t adj_mask);
extern bool l2c_is_cmd_rejected(uint8_t cmd_code, uint8_t id, tL2C_LCB* p_lcb);
extern void l2cu_send_peer_cmd_reject(tL2C_LCB* p_lcb, uint16_t reason,
uint8_t rem_id, uint16_t p1, uint16_t p2);
extern void l2cu_send_peer_connect_req(tL2C_CCB* p_ccb);
extern bool l2cu_send_peer_credit_ecfc_connect_req(tL2C_CCB* p_ccb);
extern void l2cu_send_peer_connect_rsp(tL2C_CCB* p_ccb, uint16_t result,
uint16_t status);
extern void l2cu_send_peer_config_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg);
extern void l2cu_send_peer_config_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg);
extern void l2cu_send_peer_config_rej(tL2C_CCB* p_ccb, uint8_t* p_data,
uint16_t data_len, uint16_t rej_len);
extern void l2cu_send_peer_disc_req(tL2C_CCB* p_ccb);
extern void l2cu_send_peer_disc_rsp(tL2C_LCB* p_lcb, uint8_t remote_id,
uint16_t local_cid, uint16_t remote_cid);
extern void l2cu_send_peer_echo_req(tL2C_LCB* p_lcb, uint8_t* p_data,
uint16_t data_len);
extern void l2cu_send_peer_echo_rsp(tL2C_LCB* p_lcb, uint8_t id,
uint8_t* p_data, uint16_t data_len);
extern void l2cu_send_peer_info_rsp(tL2C_LCB* p_lcb, uint8_t id,
uint16_t info_type);
extern void l2cu_reject_connection(tL2C_LCB* p_lcb, uint16_t remote_cid,
uint8_t rem_id, uint16_t result);
extern void l2cu_send_peer_info_req(tL2C_LCB* p_lcb, uint16_t info_type);
extern void l2cu_set_acl_hci_header(BT_HDR* p_buf, tL2C_CCB* p_ccb);
extern void l2cu_check_channel_congestion(tL2C_CCB* p_ccb);
extern void l2cu_disconnect_chnl(tL2C_CCB* p_ccb);
extern void l2cu_tx_complete(tL2C_TX_COMPLETE_CB_INFO* p_cbi);
#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
extern void l2cu_set_non_flushable_pbf(bool);
#endif
extern void l2cu_send_peer_ble_par_req(tL2C_LCB* p_lcb, uint16_t min_int,
uint16_t max_int, uint16_t latency,
uint16_t timeout);
extern void l2cu_send_peer_ble_par_rsp(tL2C_LCB* p_lcb, uint16_t reason,
uint8_t rem_id);
extern void l2cu_reject_ble_connection(tL2C_LCB* p_lcb, uint8_t rem_id,
uint16_t result);
extern void l2cu_send_peer_ble_credit_based_conn_res(tL2C_CCB* p_ccb,
uint16_t result);
extern void l2cu_send_peer_ble_credit_based_conn_req(tL2C_CCB* p_ccb);
extern void l2cu_send_peer_ble_flow_control_credit(tL2C_CCB* p_ccb,
uint16_t credit_value);
extern void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB* p_ccb);
extern void l2cu_send_peer_reconfig_req(tL2C_CCB* p_ccb, tL2CAP_COC_CFG_INFO* p_data);
extern bool l2cu_reconfig_coc_req(tL2CAP_COC_CHMAP_INFO* chmap_info,
uint16_t mtu, uint16_t mps);
extern bool l2cu_initialize_fixed_ccb(tL2C_LCB* p_lcb, uint16_t fixed_cid,
tL2CAP_FCR_OPTS* p_fcr);
extern void l2cu_no_dynamic_ccbs(tL2C_LCB* p_lcb);
extern void l2cu_process_fixed_chnl_resp(tL2C_LCB* p_lcb);
extern bool l2cu_is_ccb_active(tL2C_CCB* p_ccb);
extern bool l2cu_is_active_ccb_connected(const RawAddress& p_bd_addr);
extern uint8_t l2cu_allocate_coc_ccbs(tL2C_LCB* p_lcb, tL2C_CCB** p_ccb,
uint8_t* num_chnls);
extern void l2cu_set_coc_chnl_state(tL2C_CCB* p_ccb,
tL2C_CHNL_STATE chnl_state);
extern void l2cu_set_alarm_ecfc_grp(tL2C_CCB* p_ccb,
alarm_t* ecfc_conn_alarm);
extern void l2cu_release_coc_ccbs(tL2C_CCB* p_ccb);
extern void l2cu_get_coc_local_cids(uint16_t* sr_cids, tL2C_CCB* p_ccb);
extern void l2cu_set_ccbs_identifer(tL2C_CCB* p_ccb);
extern void l2cu_set_ccbs_local_id(tL2C_CCB* p_ccb);
extern void l2cu_set_ccbs_remote_id(tL2C_CCB* p_ccb);
extern void l2cu_send_disconnect_ind(uint16_t* sr_cids, uint8_t num_chnls,
tL2CA_DISCONNECT_IND_CB* disconnect_ind);
extern void l2cu_reject_coc_connection(tL2C_LCB* p_lcb, uint8_t rem_id,
uint16_t result, uint8_t num_chnls);
extern void l2cu_reset_ecfc_cids(uint16_t *sr_cids);
extern bool l2cu_check_for_valid_sr_cids(tL2C_CCB** p_ccb, uint16_t* dest_cids,
uint16_t result);
extern void l2cu_process_ecfc_pending_disconnect(tL2C_CCB** p_ccb,
uint16_t* dest_cids);
extern void l2cu_update_ccb_peer_params(tL2C_CCB* p_ccb);
extern void l2cu_send_peer_credit_based_conn_res(tL2C_CCB* p_ccb,
uint16_t result);
extern void l2cu_set_coc_remote_cids(uint16_t* dest_cids, tL2C_CCB* p_ccb);
extern void l2cu_set_coc_map_cids(tL2C_CCB* p_ccb, uint16_t* dest_cid,
uint8_t valid_chnls, uint8_t req_chnls);
extern void l2cu_process_peer_conn_request(tL2C_LCB* p_lcb,
tL2CAP_COC_CFG_INFO *p_conf_info,
tL2C_CONN_INFO* con_info,
uint16_t* dest_cid,
uint8_t num_chnls, uint8_t id);
extern void l2cu_process_peer_ecfc_conn_res(tL2C_CCB* p_ccb, uint16_t* dest_cid,
tL2C_CONN_INFO* con_info);
extern void l2cu_set_ecfc_grp_status(tL2C_CCB* p_ccb, uint8_t flag);
extern void l2cu_set_coc_conn_rsp_cids(uint16_t* dest_cids, tL2C_CCB* p_ccb,
uint8_t num_chnls);
extern const char* l2cu_get_connection_result(uint16_t result);
extern bool l2cu_set_data_length_ext(tL2C_CCB* p_ccb);
extern void l2cu_reset_sr_cid(tL2C_CCB* p_ccb);
/* Functions provided by l2c_ucd.cc
***********************************
*/
#if (L2CAP_UCD_INCLUDED == TRUE)
void l2c_ucd_delete_sec_pending_q(tL2C_LCB* p_lcb);
void l2c_ucd_enqueue_pending_out_sec_q(tL2C_CCB* p_ccb, void* p_data);
bool l2c_ucd_check_pending_info_req(tL2C_CCB* p_ccb);
bool l2c_ucd_check_pending_out_sec_q(tL2C_CCB* p_ccb);
void l2c_ucd_send_pending_out_sec_q(tL2C_CCB* p_ccb);
void l2c_ucd_discard_pending_out_sec_q(tL2C_CCB* p_ccb);
bool l2c_ucd_check_pending_in_sec_q(tL2C_CCB* p_ccb);
void l2c_ucd_send_pending_in_sec_q(tL2C_CCB* p_ccb);
void l2c_ucd_discard_pending_in_sec_q(tL2C_CCB* p_ccb);
bool l2c_ucd_check_rx_pkts(tL2C_LCB* p_lcb, BT_HDR* p_msg);
bool l2c_ucd_process_event(tL2C_CCB* p_ccb, uint16_t event, void* p_data);
#endif
/* Functions provided for Broadcom Aware
***************************************
*/
extern bool l2cu_check_feature_req(tL2C_LCB* p_lcb, uint8_t id, uint8_t* p_data,
uint16_t data_len);
extern void l2cu_check_feature_rsp(tL2C_LCB* p_lcb, uint8_t id, uint8_t* p_data,
uint16_t data_len);
extern void l2cu_send_feature_req(tL2C_CCB* p_ccb);
extern tL2C_RCB* l2cu_allocate_rcb(uint16_t psm);
extern tL2C_RCB* l2cu_find_rcb_by_psm(uint16_t psm);
extern void l2cu_release_rcb(tL2C_RCB* p_rcb);
extern void l2cu_release_coc_rcb(tL2C_RCB* p_rcb);
extern tL2C_RCB* l2cu_allocate_coc_rcb(uint16_t psm);
extern tL2C_RCB* l2cu_find_coc_rcb_by_psm(uint16_t psm);
extern uint8_t l2cu_process_peer_cfg_req(tL2C_CCB* p_ccb,
tL2CAP_CFG_INFO* p_cfg);
extern void l2cu_process_peer_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg);
extern void l2cu_process_our_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg);
extern void l2cu_process_our_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg);
extern void l2cu_device_reset(void);
extern tL2C_LCB* l2cu_find_lcb_by_state(tL2C_LINK_STATE state);
extern bool l2cu_lcb_disconnecting(void);
extern bool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport);
extern bool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport,
uint8_t initiating_phys);
extern bool l2cu_create_conn_after_switch(tL2C_LCB* p_lcb);
extern BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb,
tL2C_TX_COMPLETE_CB_INFO* p_cbi);
extern void l2cu_resubmit_pending_sec_req(const RawAddress* p_bda);
extern void l2cu_initialize_amp_ccb(tL2C_LCB* p_lcb);
extern void l2cu_adjust_out_mps(tL2C_CCB* p_ccb);
/* Functions provided by l2c_link.cc
***********************************
*/
extern bool l2c_link_hci_conn_req(const RawAddress& bd_addr);
extern bool l2c_link_hci_conn_comp(uint8_t status, uint16_t handle,
const RawAddress& p_bda);
extern bool l2c_link_hci_disc_comp(uint16_t handle, uint8_t reason);
extern bool l2c_link_hci_qos_violation(uint16_t handle);
extern void l2c_link_timeout(tL2C_LCB* p_lcb);
extern void l2c_info_resp_timer_timeout(void* data);
extern void l2c_link_check_send_pkts(tL2C_LCB* p_lcb, tL2C_CCB* p_ccb,
BT_HDR* p_buf);
extern void l2c_link_adjust_allocation(void);
extern void l2c_link_process_num_completed_pkts(uint8_t* p, uint8_t evt_len);
extern void l2c_link_process_num_completed_blocks(uint8_t controller_id,
uint8_t* p, uint16_t evt_len);
extern void l2c_link_processs_num_bufs(uint16_t num_lm_acl_bufs);
extern uint8_t l2c_link_pkts_rcvd(uint16_t* num_pkts, uint16_t* handles);
extern void l2c_link_role_changed(const RawAddress* bd_addr, uint8_t new_role,
uint8_t hci_status);
extern void l2c_link_sec_comp(const RawAddress* p_bda, tBT_TRANSPORT trasnport,
void* p_ref_data, uint8_t status);
extern void l2c_link_sec_comp2(const RawAddress& p_bda, tBT_TRANSPORT trasnport,
void* p_ref_data, uint8_t status);
extern void l2c_link_segments_xmitted(BT_HDR* p_msg);
extern void l2c_pin_code_request(const RawAddress& bd_addr);
extern void l2c_link_adjust_chnl_allocation(void);
extern void l2c_link_processs_ble_num_bufs(uint16_t num_lm_acl_bufs);
#if (L2CAP_WAKE_PARKED_LINK == TRUE)
extern bool l2c_link_check_power_mode(tL2C_LCB* p_lcb);
#define L2C_LINK_CHECK_POWER_MODE(x) l2c_link_check_power_mode((x))
#else // L2CAP_WAKE_PARKED_LINK
#define L2C_LINK_CHECK_POWER_MODE(x) (false)
#endif // L2CAP_WAKE_PARKED_LINK
#if (L2CAP_CONFORMANCE_TESTING == TRUE)
/* Used only for conformance testing */
extern void l2cu_set_info_rsp_mask(uint32_t mask);
#endif
/* Functions provided by l2c_csm.cc
***********************************
*/
extern void l2c_csm_execute(tL2C_CCB* p_ccb, uint16_t event, void* p_data);
extern void l2c_enqueue_peer_data(tL2C_CCB* p_ccb, BT_HDR* p_buf);
/* Functions provided by l2c_fcr.cc
***********************************
*/
extern void l2c_fcr_cleanup(tL2C_CCB* p_ccb);
extern void l2c_fcr_proc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf);
extern void l2c_fcr_proc_tout(tL2C_CCB* p_ccb);
extern void l2c_fcr_proc_ack_tout(tL2C_CCB* p_ccb);
extern void l2c_fcr_send_S_frame(tL2C_CCB* p_ccb, uint16_t function_code,
uint16_t pf_bit);
extern BT_HDR* l2c_fcr_clone_buf(BT_HDR* p_buf, uint16_t new_offset,
uint16_t no_of_bytes);
extern bool l2c_fcr_is_flow_controlled(tL2C_CCB* p_ccb);
extern BT_HDR* l2c_fcr_get_next_xmit_sdu_seg(tL2C_CCB* p_ccb,
uint16_t max_packet_length);
extern void l2c_fcr_start_timer(tL2C_CCB* p_ccb);
extern void l2c_lcc_proc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf);
extern BT_HDR* l2c_lcc_get_next_xmit_sdu_seg(tL2C_CCB* p_ccb,
uint16_t max_packet_length);
/* Configuration negotiation */
extern uint8_t l2c_fcr_chk_chan_modes(tL2C_CCB* p_ccb);
extern bool l2c_fcr_chk_remote_ecfc_support(tL2C_CCB* p_ccb);
extern bool l2c_fcr_adj_our_req_options(tL2C_CCB* p_ccb,
tL2CAP_CFG_INFO* p_cfg);
extern void l2c_fcr_adj_our_rsp_options(tL2C_CCB* p_ccb,
tL2CAP_CFG_INFO* p_peer_cfg);
extern bool l2c_fcr_renegotiate_chan(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg);
extern uint8_t l2c_fcr_process_peer_cfg_req(tL2C_CCB* p_ccb,
tL2CAP_CFG_INFO* p_cfg);
extern void l2c_fcr_adj_monitor_retran_timeout(tL2C_CCB* p_ccb);
extern void l2c_fcr_stop_timer(tL2C_CCB* p_ccb);
extern void l2c_fcr_buffer_l2cap_coc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf);
extern void l2c_fcr_monitor_rx_buffer(void* p_ccb);
extern void l2c_fcr_start_rx_buffer_mon_timer(tL2C_CCB* p_ccb);
/* Functions provided by l2c_ble.cc
***********************************
*/
extern bool l2cble_create_conn(tL2C_LCB* p_lcb);
extern void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p,
uint16_t pkt_len);
extern void l2cble_conn_comp(uint16_t handle, uint8_t role,
const RawAddress& bda, tBLE_ADDR_TYPE type,
uint16_t conn_interval, uint16_t conn_latency,
uint16_t conn_timeout);
extern void l2cble_notify_le_connection(const RawAddress& bda);
extern void l2c_ble_link_adjust_allocation(void);
extern void l2cble_process_conn_update_evt(uint16_t handle, uint8_t status,
uint16_t interval, uint16_t latency,
uint16_t timeout);
extern void l2cble_credit_based_conn_req(tL2C_CCB* p_ccb);
extern void l2cble_credit_based_conn_res(tL2C_CCB* p_ccb, uint16_t result);
extern tL2CAP_LE_RESULT_CODE l2ble_sec_access_req(const RawAddress& bd_addr,
uint16_t psm,
bool is_originator,
tL2CAP_SEC_CBACK* p_callback,
void* p_ref_data);
#if (BLE_LLT_INCLUDED == TRUE)
extern void l2cble_process_rc_param_request_evt(uint16_t handle,
uint16_t int_min,
uint16_t int_max,
uint16_t latency,
uint16_t timeout);
#endif
extern void l2cble_update_data_length(tL2C_LCB* p_lcb);
extern void l2cble_set_fixed_channel_tx_data_length(
const RawAddress& remote_bda, uint16_t fix_cid, uint16_t tx_mtu);
extern void l2cble_process_data_length_change_event(uint16_t handle,
uint16_t tx_data_len,
uint16_t rx_data_len);
extern void l2cu_process_fixed_disc_cback(tL2C_LCB* p_lcb);
extern void l2cble_validate_mps_for_ecfc_group(tL2C_LCB* p_lcb, uint16_t tx_data_len);
extern void l2cu_send_flow_control_credit(tL2C_CCB* p_ccb,
uint16_t credit_value);
extern void l2cu_post_data_ind_cb_to_btu(tL2C_CCB* p_ccb);
extern uint16_t l2cu_validate_mps_for_chnls(uint16_t mps, uint16_t *cid,
uint8_t num_chnls, bool isOutgoing);
extern uint16_t l2cu_validate_mtu_for_chnls(uint16_t mtu, uint16_t *cid,
uint8_t num_chnls, bool isOutgoing);
extern void l2cu_send_peer_reconfig_req(tL2C_CCB* p_ccb, tL2C_CFG_REQ_PARAM *cfg);
extern void l2cu_send_peer_rcfg_rsp(tL2C_LCB* , tL2C_CCB* , tL2C_CFG_REQ_PARAM *);
extern void l2cu_set_multi_coc_chnl_cfg(tL2C_LCB* p_lcb, tL2C_CFG_REQ_PARAM* cfg,
tL2C_CHNL_STATE state, uint8_t cfg_state);
extern void l2cu_find_req_params_for_peer_rcfg_rsp(tL2C_LCB* p_lcb,
uint16_t result, uint8_t id);
extern void l2cu_process_peer_rcfg_rsp(tL2C_CFG_REQ_PARAM *cfg);
extern bool l2cu_process_peer_rcfg_req(tL2C_CFG_REQ_PARAM *cfg);
extern void l2cu_process_local_rcfg_rsp(tL2C_CFG_REQ_PARAM *rcfg);
extern bool l2cu_validate_cids_in_use_status(tL2CAP_COC_CHMAP_INFO *chnl_inf,
tL2C_CCB **p_active_ccb);
extern const char* l2cu_get_reconfig_result(uint16_t result);
extern void l2cu_send_peer_coc_disc_req(tL2C_CCB* p_ccb);
extern void l2cu_clear_reconfig_params(tL2C_CCB* p_ccb);
extern tL2C_CCB* l2cu_find_ccb_by_l2cap_id(tL2C_LCB* p_lcb, uint16_t l2cap_id);
bool l2cu_is_unaccepted_coc_result_code(uint16_t result);
extern void l2cble_process_subrate_change_evt(uint16_t handle, uint8_t status,
uint16_t subrate_factor, uint16_t peripheral_latency,
uint16_t cont_num, uint16_t timeout);
#endif
|