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
|
/*****************************************************************************
**
** Name: l2c_int.h
**
** Description: This file contains L2CAP internal definitions
**
** Copyright (c) 1999-2012, Broadcom Corp., All Rights Reserved.
** Broadcom Bluetooth Core. Proprietary and confidential.
******************************************************************************/
#ifndef L2C_INT_H
#define L2C_INT_H
#include "l2c_api.h"
#include "l2cdefs.h"
#include "gki.h"
#include "btm_api.h"
#define L2CAP_MIN_MTU 48 /* Minimum acceptable MTU is 48 bytes */
/* Timeouts. Since L2CAP works off a 1-second list, all are in seconds.
*/
#define L2CAP_LINK_ROLE_SWITCH_TOUT 10 /* 10 seconds */
#define L2CAP_LINK_CONNECT_TOUT 60 /* 30 seconds */
#define L2CAP_LINK_CONNECT_TOUT_EXT 120 /* 120 seconds */
#define L2CAP_ECHO_RSP_TOUT 30 /* 30 seconds */
#define L2CAP_LINK_FLOW_CONTROL_TOUT 2 /* 2 seconds */
#define L2CAP_LINK_DISCONNECT_TOUT 30 /* 30 seconds */
#ifndef L2CAP_CHNL_CONNECT_TOUT /* BTIF needs to override for internal project needs */
#define L2CAP_CHNL_CONNECT_TOUT 60 /* 60 seconds */
#endif
#define L2CAP_CHNL_CONNECT_TOUT_EXT 120 /* 120 seconds */
#define L2CAP_CHNL_CFG_TIMEOUT 30 /* 30 seconds */
#define L2CAP_CHNL_DISCONNECT_TOUT 10 /* 10 seconds */
#define L2CAP_DELAY_CHECK_SM4 2 /* 2 seconds */
#define L2CAP_WAIT_INFO_RSP_TOUT 3 /* 3 seconds */
#define L2CAP_WAIT_UNPARK_TOUT 2 /* 2 seconds */
#define L2CAP_LINK_INFO_RESP_TOUT 2 /* 2 seconds */
#define L2CAP_BLE_LINK_CONNECT_TOUT 30 /* 30 seconds */
/* quick timer uses millisecond unit */
#define L2CAP_DEFAULT_RETRANS_TOUT 2000 /* 2000 milliseconds */
#define L2CAP_DEFAULT_MONITOR_TOUT 12000 /* 12000 milliseconds */
#define L2CAP_FCR_ACK_TOUT 200 /* 200 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 clodes 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.
*/
#define L2CEVT_LP_CONNECT_CFM 0 /* Lower layer connect confirm */
#define L2CEVT_LP_CONNECT_CFM_NEG 1 /* Lower layer connect confirm (failed) */
#define L2CEVT_LP_CONNECT_IND 2 /* Lower layer connect indication */
#define L2CEVT_LP_DISCONNECT_IND 3 /* Lower layer disconnect indication */
#define L2CEVT_LP_QOS_CFM 4 /* Lower layer QOS confirmation */
#define L2CEVT_LP_QOS_CFM_NEG 5 /* Lower layer QOS confirmation (failed)*/
#define L2CEVT_LP_QOS_VIOLATION_IND 6 /* Lower layer QOS violation indication */
#define L2CEVT_SEC_COMP 7 /* Security cleared successfully */
#define L2CEVT_SEC_COMP_NEG 8 /* Security procedure failed */
#define L2CEVT_L2CAP_CONNECT_REQ 10 /* Peer connection request */
#define L2CEVT_L2CAP_CONNECT_RSP 11 /* Peer connection response */
#define L2CEVT_L2CAP_CONNECT_RSP_PND 12 /* Peer connection response pending */
#define L2CEVT_L2CAP_CONNECT_RSP_NEG 13 /* Peer connection response (failed) */
#define L2CEVT_L2CAP_CONFIG_REQ 14 /* Peer configuration request */
#define L2CEVT_L2CAP_CONFIG_RSP 15 /* Peer configuration response */
#define L2CEVT_L2CAP_CONFIG_RSP_NEG 16 /* Peer configuration 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 */
#define L2CEVT_L2CA_CONNECT_REQ 21 /* Upper layer connect request */
#define L2CEVT_L2CA_CONNECT_RSP 22 /* Upper layer connect response */
#define L2CEVT_L2CA_CONNECT_RSP_NEG 23 /* Upper layer connect response (failed)*/
#define L2CEVT_L2CA_CONFIG_REQ 24 /* Upper layer config request */
#define L2CEVT_L2CA_CONFIG_RSP 25 /* Upper layer config response */
#define L2CEVT_L2CA_CONFIG_RSP_NEG 26 /* Upper layer config response (failed) */
#define L2CEVT_L2CA_DISCONNECT_REQ 27 /* Upper layer disconnect request */
#define L2CEVT_L2CA_DISCONNECT_RSP 28 /* Upper layer disconnect response */
#define L2CEVT_L2CA_DATA_READ 29 /* Upper layer data read */
#define L2CEVT_L2CA_DATA_WRITE 30 /* Upper layer data write */
#define L2CEVT_L2CA_FLUSH_REQ 31 /* Upper layer 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 */
/* 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 */
#define L2CAP_MIN_RETRANS_TOUT 2000 /* Min retransmission timeout if no flush timeout or PBF */
#define L2CAP_MIN_MONITOR_TOUT 12000 /* Min monitor timeout if no flush timeout or PBF */
#define L2CAP_MAX_FCR_CFG_TRIES 2 /* Config attempts before disconnecting */
/* Only compiled in when in test mode. Production devices must not include
*/
#if L2CAP_CORRUPT_ERTM_PKTS == TRUE
/* These are used for conformance and corruption testing only */
typedef struct
{
BOOLEAN in_use; /* TRUE if test in progress */
UINT8 type; /* Type of test to run or turns off random test */
UINT8 freq; /* One-shot or random */
BOOLEAN is_rx; /* TRUE if incoming packets */
UINT16 count; /* How many I-frames to drop in a row; used only with one-shot tests */
} tL2C_FCR_TEST_CFG;
typedef struct
{
BOOLEAN in_use; /* TRUE if test in progress */
UINT8 skip_sframe_count; /* Number of S-Frames to skip sending */
} tL2C_FCR_CFM_TEST_CB;
typedef struct
{
tL2C_FCR_TEST_CFG cfg; /* Current corruption test configuration */
tL2C_FCR_CFM_TEST_CB cfm; /* Conformance test structure */
} tL2C_FCR_TEST_CB;
#endif /* L2CAP_CORRUPT_ERTM_PKTS == TRUE */
typedef struct
{
UINT8 next_tx_seq; /* Next sequence number to be Tx'ed */
UINT8 last_rx_ack; /* Last sequence number ack'ed by the peer */
UINT8 next_seq_expected; /* Next peer sequence number expected */
UINT8 last_ack_sent; /* Last peer sequence number ack'ed */
UINT8 num_tries; /* Number of retries to send a packet */
UINT8 max_held_acks; /* Max acks we can hold before sending */
BOOLEAN remote_busy; /* TRUE if peer has flowed us off */
BOOLEAN local_busy; /* TRUE if we have flowed off the peer */
BOOLEAN rej_sent; /* Reject was sent */
BOOLEAN srej_sent; /* Selective Reject was sent */
BOOLEAN wait_ack; /* Transmitter is waiting ack (poll sent) */
BOOLEAN rej_after_srej; /* Send a REJ when SREJ clears */
BOOLEAN send_f_rsp; /* We need to send an F-bit response */
UINT16 rx_sdu_len; /* Length of the SDU being received */
BT_HDR *p_rx_sdu; /* Buffer holding the SDU being received */
BUFFER_Q waiting_for_ack_q; /* Buffers sent and waiting for peer to ack */
BUFFER_Q srej_rcv_hold_q; /* Buffers rcvd but held pending SREJ rsp */
BUFFER_Q retrans_q; /* Buffers being retransmitted */
TIMER_LIST_ENT ack_timer; /* Timer delaying RR */
TIMER_LIST_ENT mon_retrans_timer; /* Timer Monitor or Retransmission */
#if (L2CAP_ERTM_STATS == TRUE)
UINT32 connect_tick_count; /* Time channel was established */
UINT32 ertm_pkt_counts[2]; /* Packets sent and received */
UINT32 ertm_byte_counts[2]; /* Bytes sent and received */
UINT32 s_frames_sent[4]; /* S-frames sent (RR, REJ, RNR, SREJ) */
UINT32 s_frames_rcvd[4]; /* S-frames rcvd (RR, REJ, RNR, SREJ) */
UINT32 xmit_window_closed; /* # of times the xmit window was closed */
UINT32 controller_idle; /* # of times less than 2 packets in controller */
/* when the xmit window was closed */
UINT32 pkts_retransmitted; /* # of packets that were retransmitted */
UINT32 retrans_touts; /* # of retransmission timouts */
UINT32 xmit_ack_touts; /* # of xmit ack timouts */
#define L2CAP_ERTM_STATS_NUM_AVG 10
#define L2CAP_ERTM_STATS_AVG_NUM_SAMPLES 100
UINT32 ack_delay_avg_count;
UINT32 ack_delay_avg_index;
UINT32 throughput_start;
UINT32 throughput[L2CAP_ERTM_STATS_NUM_AVG];
UINT32 ack_delay_avg[L2CAP_ERTM_STATS_NUM_AVG];
UINT32 ack_delay_min[L2CAP_ERTM_STATS_NUM_AVG];
UINT32 ack_delay_max[L2CAP_ERTM_STATS_NUM_AVG];
UINT32 ack_q_count_avg[L2CAP_ERTM_STATS_NUM_AVG];
UINT32 ack_q_count_min[L2CAP_ERTM_STATS_NUM_AVG];
UINT32 ack_q_count_max[L2CAP_ERTM_STATS_NUM_AVG];
#endif
#if L2CAP_CORRUPT_ERTM_PKTS == TRUE
tL2C_FCR_TEST_CB test_cb; /* Used for SVT and UPF testing */
#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 state;
tL2CAP_UCD_CB_INFO cb_info;
} tL2C_UCD_REG;
#endif
typedef struct
{
BOOLEAN in_use;
UINT16 psm;
UINT16 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;
} tL2C_RCB;
/* 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
{
BOOLEAN in_use; /* TRUE when in use, FALSE when not */
tL2C_CHNL_STATE chnl_state; /* Channel state */
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 local_cid; /* Local CID */
UINT16 remote_cid; /* Remote CID */
TIMER_LIST_ENT timer_entry; /* CCB Timer List Entry */
tL2C_RCB *p_rcb; /* Registration CB for this Channel */
#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 config_done; /* Configuration flag word */
UINT8 local_id; /* Transaction ID for local trans */
UINT8 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 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 */
BUFFER_Q xmit_hold_q; /* Transmit data hold queue */
BOOLEAN cong_sent; /* Set when congested status sent */
UINT16 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 tx_mps; /* TX MPS adjusted based on current controller */
UINT16 max_rx_mtu;
UINT8 fcr_cfg_tries; /* Max number of negotiation attempts */
BOOLEAN peer_cfg_already_rejected; /* If mode rejected once, set to TRUE */
BOOLEAN 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 bypass_fcs;
#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
BOOLEAN is_flushable; /* TRUE if channel is flushable */
#endif
#if (L2CAP_NUM_FIXED_CHNLS > 0) || (L2CAP_UCD_INCLUDED == TRUE)
UINT16 fixed_chnl_idle_tout; /* Idle timeout to use for the fixed channel */
#endif
} 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 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 num_ccb; /* number of channels in priority group */
UINT8 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
{
BOOLEAN in_use; /* TRUE when in use, FALSE when not */
tL2C_LINK_STATE link_state;
TIMER_LIST_ENT timer_entry; /* Timer list entry for timeout evt */
UINT16 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 */
TIMER_LIST_ENT info_timer_entry; /* Timer entry for info resp timeout evt */
BD_ADDR remote_bd_addr; /* The BD address of the remote */
UINT8 link_role; /* Master or slave */
UINT8 id;
tL2CA_ECHO_RSP_CB *p_echo_rsp_cb; /* Echo response callback */
UINT16 idle_timeout; /* Idle timeout */
BOOLEAN is_bonding; /* True - link active only for bonding */
UINT16 link_flush_tout; /* Flush timeout used */
UINT16 link_xmit_quota; /* Num outstanding pkts allowed */
UINT16 sent_not_acked; /* Num packets sent but not acked */
BOOLEAN partial_segment_being_sent; /* Set TRUE when a partial segment */
/* is being sent. */
BOOLEAN w4_info_rsp; /* TRUE when info request is active */
UINT8 info_rx_bits; /* set 1 if received info type */
UINT32 peer_ext_fea; /* Peer's extended features mask */
BUFFER_Q link_xmit_data_q; /* Transmit data buffer queue */
UINT8 peer_chnl_mask[L2CAP_FIXED_CHNL_ARRAY_SIZE];
#if (L2CAP_UCD_INCLUDED == TRUE)
UINT16 ucd_mtu; /* peer MTU on UCD */
BUFFER_Q ucd_out_sec_pending_q; /* Security pending outgoing UCD packet */
BUFFER_Q ucd_in_sec_pending_q; /* Security pending incoming UCD packet */
#endif
#if (L2CAP_HOST_FLOW_CTRL == TRUE)
UINT16 link_pkts_unacked; /* Packets received but not acked */
UINT16 link_ack_thresh; /* Threshold at which to ack pkts */
#endif
BT_HDR *p_hcit_rcv_acl; /* Current HCIT ACL buf being rcvd */
UINT16 idle_timeout_sv; /* Save current Idle timeout */
UINT8 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 disc_reason;
#endif
#if (BLE_INCLUDED == TRUE)
BOOLEAN is_ble_link;
tBLE_ADDR_TYPE ble_addr_type;
#define UPD_ENABLED 0 /* If peer requests update, we will change params */
#define UPD_DISABLED 1 /* application requested not to update */
#define UPD_PENDING 2 /* while updates are disabled, peer requested new parameters */
#define UPD_UPDATED 3 /* peer updated connection parameters */
UINT8 upd_disabled;
UINT16 min_interval; /* parameters as requested by peripheral */
UINT16 max_interval;
UINT16 latency;
UINT16 timeout;
#endif
#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 rr_pri; /* current serving priority group */
#endif
} tL2C_LCB;
/* Define the L2CAP control structure
*/
typedef struct
{
UINT8 l2cap_trace_level;
UINT16 controller_xmit_window; /* Total ACL window for all links */
UINT16 round_robin_quota; /* Round-robin link quota */
UINT16 round_robin_unacked; /* Round-robin unacked */
BOOLEAN check_round_robin; /* Do a round robin check */
BOOLEAN 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 desire_role; /* desire to be master/slave when accepting a connection */
BOOLEAN disallow_switch; /* FALSE, to allow switch at create conn */
UINT16 num_lm_acl_bufs; /* # of ACL buffers on controller */
UINT16 idle_timeout; /* Idle timeout */
BUFFER_Q rcv_hold_q; /* Recv pending queue */
TIMER_LIST_ENT rcv_hold_tle; /* Timer list entry for rcv hold */
tL2C_LCB *p_cur_hcit_lcb; /* Current HCI Transport buffer */
UINT16 num_links_active; /* Number of links active */
#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
UINT16 non_flushable_pbf; /* L2CAP_PKT_START_NON_FLUSHABLE if controller supports */
/* Otherwise, L2CAP_PKT_START */
BOOLEAN is_flush_active; /* TRUE if an HCI_Enhanced_Flush has been sent */
#endif
#if L2CAP_CONFORMANCE_TESTING == TRUE
UINT32 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
#if (BLE_INCLUDED == TRUE)
BOOLEAN is_ble_connecting;
BD_ADDR ble_connecting_bda;
UINT16 controller_le_xmit_window; /* Total ACL window for all links */
UINT16 num_lm_ble_bufs; /* # of ACL buffers on controller */
#endif
tL2CA_ECHO_DATA_CB *p_echo_data_cb; /* Echo data callback */
#if (defined(L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE) && (L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE == TRUE))
UINT16 high_pri_min_xmit_quota; /* Minimum number of ACL credit for high priority link */
#endif /* (L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE == TRUE) */
UINT16 dyn_psm;
} 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
{
BD_ADDR bd_addr; /* Remote BD address */
UINT8 status; /* Connection status */
UINT16 psm; /* PSM of the connection */
UINT16 l2cap_result; /* L2CAP result */
UINT16 l2cap_status; /* L2CAP status */
UINT16 remote_cid; /* Remote CID */
} tL2C_CONN_INFO;
typedef void (tL2C_FCR_MGMT_EVT_HDLR) (UINT8, tL2C_CCB *);
/* 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 (!defined(L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE) || (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
#ifdef __cplusplus
extern "C" {
#endif
/* L2CAP global data
************************************
*/
#if (!defined L2C_DYNAMIC_MEMORY) || (L2C_DYNAMIC_MEMORY == FALSE)
L2C_API extern tL2C_CB l2cb;
#else
L2C_API extern tL2C_CB *l2c_cb_ptr;
#define l2cb (*l2c_cb_ptr)
#endif
/* Functions provided by l2c_main.c
************************************
*/
extern void l2c_init (void);
extern void l2c_process_timeout (TIMER_LIST_ENT *p_tle);
extern UINT8 l2c_data_write (UINT16 cid, BT_HDR *p_data, UINT16 flag);
extern void l2c_rcv_acl_data (BT_HDR *p_msg);
extern void l2c_process_held_packets (BOOLEAN timed_out);
/* Functions provided by l2c_utils.c
************************************
*/
extern tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding);
extern BOOLEAN l2cu_start_post_bond_timer (UINT16 handle);
extern void l2cu_release_lcb (tL2C_LCB *p_lcb);
extern tL2C_LCB *l2cu_find_lcb_by_bd_addr (BD_ADDR p_bd_addr);
extern tL2C_LCB *l2cu_find_lcb_by_handle (UINT16 handle);
extern void l2cu_update_lcb_4_bonding (BD_ADDR p_bd_addr, BOOLEAN is_bonding);
extern UINT8 l2cu_get_conn_role (tL2C_LCB *p_this_lcb);
extern BOOLEAN l2cu_set_acl_priority (BD_ADDR bd_addr, UINT8 priority, BOOLEAN 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 cid);
extern void l2cu_release_ccb (tL2C_CCB *p_ccb);
extern tL2C_CCB *l2cu_find_ccb_by_cid (tL2C_LCB *p_lcb, UINT16 local_cid);
extern tL2C_CCB *l2cu_find_ccb_by_remote_cid (tL2C_LCB *p_lcb, UINT16 remote_cid);
extern void l2cu_adj_id (tL2C_LCB *p_lcb, UINT8 adj_mask);
extern void l2cu_send_peer_cmd_reject (tL2C_LCB *p_lcb, UINT16 reason,
UINT8 rem_id,UINT16 p1, UINT16 p2);
extern void l2cu_send_peer_connect_req (tL2C_CCB *p_ccb);
extern void l2cu_send_peer_connect_rsp (tL2C_CCB *p_ccb, UINT16 result, UINT16 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 *p_data, UINT16 data_len, UINT16 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 remote_id, UINT16 local_cid, UINT16 remote_cid);
extern void l2cu_send_peer_echo_req (tL2C_LCB *p_lcb, UINT8 *p_data, UINT16 data_len);
extern void l2cu_send_peer_echo_rsp (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len);
extern void l2cu_send_peer_info_rsp (tL2C_LCB *p_lcb, UINT8 id, UINT16 info_type);
extern void l2cu_reject_connection (tL2C_LCB *p_lcb, UINT16 remote_cid, UINT8 rem_id, UINT16 result);
extern void l2cu_send_peer_info_req (tL2C_LCB *p_lcb, UINT16 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);
#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
extern void l2cu_set_non_flushable_pbf(BOOLEAN);
#endif
#if (BLE_INCLUDED == TRUE)
extern void l2cu_send_peer_ble_par_req (tL2C_LCB *p_lcb, UINT16 min_int, UINT16 max_int, UINT16 latency, UINT16 timeout);
extern void l2cu_send_peer_ble_par_rsp (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id);
#endif
extern BOOLEAN l2cu_initialize_fixed_ccb (tL2C_LCB *p_lcb, UINT16 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);
/* Functions provided by l2c_ucd.c
************************************
*/
#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);
BOOLEAN l2c_ucd_check_pending_info_req(tL2C_CCB *p_ccb);
BOOLEAN 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);
BOOLEAN 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);
BOOLEAN l2c_ucd_check_rx_pkts(tL2C_LCB *p_lcb, BT_HDR *p_msg);
BOOLEAN l2c_ucd_process_event(tL2C_CCB *p_ccb, UINT16 event, void *p_data);
#endif
#if (BLE_INCLUDED == TRUE)
extern void l2cu_send_peer_ble_par_req (tL2C_LCB *p_lcb, UINT16 min_int, UINT16 max_int, UINT16 latency, UINT16 timeout);
extern void l2cu_send_peer_ble_par_rsp (tL2C_LCB *p_lcb, UINT16 reason, UINT8 rem_id);
#endif
extern BOOLEAN l2cu_initialize_fixed_ccb (tL2C_LCB *p_lcb, UINT16 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);
/* Functions provided for Broadcom Aware
****************************************
*/
extern BOOLEAN l2cu_check_feature_req (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len);
extern void l2cu_check_feature_rsp (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len);
extern void l2cu_send_feature_req (tL2C_CCB *p_ccb);
extern tL2C_RCB *l2cu_allocate_rcb (UINT16 psm);
extern tL2C_RCB *l2cu_find_rcb_by_psm (UINT16 psm);
extern void l2cu_release_rcb (tL2C_RCB *p_rcb);
extern UINT8 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 BOOLEAN l2cu_lcb_disconnecting (void);
extern BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb);
extern BOOLEAN l2cu_create_conn_after_switch (tL2C_LCB *p_lcb);
extern BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb);
extern void l2cu_resubmit_pending_sec_req (BD_ADDR 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.c
************************************
*/
extern BOOLEAN l2c_link_hci_conn_req (BD_ADDR bd_addr);
extern BOOLEAN l2c_link_hci_conn_comp (UINT8 status, UINT16 handle, BD_ADDR p_bda);
extern BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason);
extern BOOLEAN l2c_link_hci_qos_violation (UINT16 handle);
extern void l2c_link_timeout (tL2C_LCB *p_lcb);
extern void l2c_info_timeout (tL2C_LCB *p_lcb);
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 *p);
extern void l2c_link_process_num_completed_blocks (UINT8 controller_id, UINT8 *p, UINT16 evt_len);
extern void l2c_link_processs_num_bufs (UINT16 num_lm_acl_bufs);
extern UINT8 l2c_link_pkts_rcvd (UINT16 *num_pkts, UINT16 *handles);
extern void l2c_link_role_changed (BD_ADDR bd_addr, UINT8 new_role, UINT8 hci_status);
extern void l2c_link_sec_comp (BD_ADDR p_bda, void *p_ref_data, UINT8 status);
extern void l2c_link_segments_xmitted (BT_HDR *p_msg);
extern void l2c_pin_code_request (BD_ADDR bd_addr);
extern void l2c_link_adjust_chnl_allocation (void);
#if (BLE_INCLUDED == TRUE)
extern void l2c_link_processs_ble_num_bufs (UINT16 num_lm_acl_bufs);
#endif
#if ((BTM_PWR_MGR_INCLUDED == TRUE) && L2CAP_WAKE_PARKED_LINK == TRUE)
extern BOOLEAN l2c_link_check_power_mode ( tL2C_LCB *p_lcb );
#define L2C_LINK_CHECK_POWER_MODE(x) l2c_link_check_power_mode ((x))
#else
#define L2C_LINK_CHECK_POWER_MODE(x) (FALSE)
#endif
#if L2CAP_CONFORMANCE_TESTING == TRUE
/* Used only for conformance testing */
L2C_API extern void l2cu_set_info_rsp_mask (UINT32 mask);
#endif
/* Functions provided by l2c_csm.c
************************************
*/
extern void l2c_csm_execute (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
L2C_API extern BT_HDR *l2cap_link_chk_pkt_start(BT_HDR *); /* Called at start of rcv to check L2CAP segmentation */
L2C_API extern BOOLEAN l2cap_link_chk_pkt_end (void); /* Called at end of rcv to check L2CAP segmentation */
L2C_API extern void l2c_enqueue_peer_data (tL2C_CCB *p_ccb, BT_HDR *p_buf);
/* Functions provided by l2c_fcr.c
************************************
*/
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 function_code, UINT16 pf_bit);
extern BT_HDR *l2c_fcr_clone_buf (BT_HDR *p_buf, UINT16 new_offset, UINT16 no_of_bytes, UINT8 pool);
extern BOOLEAN l2c_fcr_is_flow_controlled (tL2C_CCB *p_ccb);
extern BT_HDR *l2c_fcr_get_next_xmit_sdu_seg (tL2C_CCB *p_ccb, UINT16 max_packet_length);
extern void l2c_fcr_start_timer (tL2C_CCB *p_ccb);
/* Configuration negotiation */
extern UINT8 l2c_fcr_chk_chan_modes (tL2C_CCB *p_ccb);
extern BOOLEAN 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 BOOLEAN l2c_fcr_renegotiate_chan(tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg);
extern UINT8 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);
/* Functions provided by l2c_ble.c
************************************
*/
#if (BLE_INCLUDED == TRUE)
extern BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb);
extern void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len);
extern void l2cble_conn_comp (UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout);
#endif
#ifdef __cplusplus
}
#endif
#endif
|