Bluetooth: L2CAP_BR: Enable Retransmission and Flow control
Enable signaling channel configuration for retransmission and Flow control feature. Send I-frame and S-frame. Support retransmission and Flow control for sending. Receive and handle I-frame and S-frame. Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
This commit is contained in:
parent
ddcb8611ed
commit
d2a10833dd
6 changed files with 4230 additions and 171 deletions
|
@ -271,42 +271,215 @@ struct bt_l2cap_le_chan {
|
|||
*/
|
||||
#define BT_L2CAP_LE_CHAN(_ch) CONTAINER_OF(_ch, struct bt_l2cap_le_chan, chan)
|
||||
|
||||
/** L2CAP Endpoint Link Mode. Basic mode. */
|
||||
#define BT_L2CAP_BR_LINK_MODE_BASIC 0x00
|
||||
/** L2CAP Endpoint Link Mode. Retransmission mode. */
|
||||
#define BT_L2CAP_BR_LINK_MODE_RET 0x01
|
||||
/** L2CAP Endpoint Link Mode. Flow control mode. */
|
||||
#define BT_L2CAP_BR_LINK_MODE_FC 0x02
|
||||
/** L2CAP Endpoint Link Mode. Enhance retransmission mode. */
|
||||
#define BT_L2CAP_BR_LINK_MODE_ERET 0x03
|
||||
/** L2CAP Endpoint Link Mode. Streaming mode. */
|
||||
#define BT_L2CAP_BR_LINK_MODE_STREAM 0x04
|
||||
|
||||
/** Frame Check Sequence type. No FCS. */
|
||||
#define BT_L2CAP_BR_FCS_NO 0x00
|
||||
/** Frame Check Sequence type. 16-bit FCS. */
|
||||
#define BT_L2CAP_BR_FCS_16BIT 0x01
|
||||
|
||||
/** @brief BREDR L2CAP Endpoint structure. */
|
||||
struct bt_l2cap_br_endpoint {
|
||||
/** Endpoint Channel Identifier (CID) */
|
||||
uint16_t cid;
|
||||
uint16_t cid;
|
||||
/** Endpoint Maximum Transmission Unit */
|
||||
uint16_t mtu;
|
||||
uint16_t mtu;
|
||||
#if defined(CONFIG_BT_L2CAP_RET_FC) || defined(__DOXYGEN__)
|
||||
/** Endpoint Link Mode.
|
||||
* The value is defined as BT_L2CAP_BR_LINK_MODE_*
|
||||
*/
|
||||
uint8_t mode;
|
||||
/** Whether Endpoint Link Mode is optional
|
||||
* If the `optional` is true, the `mode` could be
|
||||
* changed according to the extended feature and
|
||||
* peer configuration from L2CAP configuration
|
||||
* response and request.
|
||||
* Otherwise, if the channel configuration process
|
||||
* does not meet the set mode, the L2CAP channel
|
||||
* will be disconnected.
|
||||
*/
|
||||
bool optional;
|
||||
/** Endpoint Maximum Transmit
|
||||
* The field is used to set the max retransmission
|
||||
* count.
|
||||
* For `RET`, `FC`, and `ERET`, it should be not
|
||||
* less 1.
|
||||
* For `STREAM`, it should be 0.
|
||||
*/
|
||||
uint8_t max_transmit;
|
||||
/** Endpoint Retransmission Timeout
|
||||
* The field is configured by
|
||||
* `@kconfig{BT_L2CAP_BR_RET_TIMEOUT}`
|
||||
* The field should be no more than the field
|
||||
* `monitor_timeout`.
|
||||
*/
|
||||
uint16_t ret_timeout;
|
||||
/** Endpoint Monitor Timeout
|
||||
* The field is configured by
|
||||
* `@kconfig{BT_L2CAP_BR_MONITOR_TIMEOUT}`
|
||||
*/
|
||||
uint16_t monitor_timeout;
|
||||
/** Endpoint Maximum PDU payload Size */
|
||||
uint16_t mps;
|
||||
/** Endpoint Maximum Window Size
|
||||
* MAX supported window size is configured by
|
||||
* `@kconfig{BT_L2CAP_MAX_WINDOW_SIZE}`. The field
|
||||
* should be no more then `CONFIG_BT_L2CAP_MAX_WINDOW_SIZE`.
|
||||
*/
|
||||
uint16_t max_window;
|
||||
/** Endpoint FCS Type
|
||||
* The value is defined as BT_L2CAP_BR_FCS_*
|
||||
* The default setting should be BT_L2CAP_BR_FCS_16BIT.
|
||||
* For FC and RET, the FCS type should be
|
||||
* BT_L2CAP_BR_FCS_16BIT.
|
||||
* For ERET and STREAM, the FCS type is optional. If
|
||||
* the field is not default value, the local will include
|
||||
* FCS option in configuration request packet if both side
|
||||
* support `FCS Option`.
|
||||
*/
|
||||
uint8_t fcs;
|
||||
/** Endpoint Extended Control.
|
||||
* If this field is true, and both side support
|
||||
* `Extended Window size feature`, the local will
|
||||
* include `extended window size` option in configuration
|
||||
* request packet.
|
||||
*/
|
||||
bool extended_control;
|
||||
#endif /* CONFIG_BT_L2CAP_RET_FC */
|
||||
};
|
||||
|
||||
/** I-Frame transmission window for none `BASIC` mode L2cap connected channel. */
|
||||
struct bt_l2cap_br_window {
|
||||
sys_snode_t node;
|
||||
|
||||
/** tx seq */
|
||||
uint16_t tx_seq;
|
||||
/** data len */
|
||||
uint16_t len;
|
||||
/** data address */
|
||||
uint8_t *data;
|
||||
/** Transmit Counter */
|
||||
uint8_t transmit_counter;
|
||||
/** SAR flag */
|
||||
uint8_t sar;
|
||||
/** srej flag */
|
||||
bool srej;
|
||||
/* Save PDU state */
|
||||
struct net_buf_simple_state pdu;
|
||||
};
|
||||
|
||||
/** @brief BREDR L2CAP Channel structure. */
|
||||
struct bt_l2cap_br_chan {
|
||||
/** Common L2CAP channel reference object */
|
||||
struct bt_l2cap_chan chan;
|
||||
struct bt_l2cap_chan chan;
|
||||
/** Channel Receiving Endpoint */
|
||||
struct bt_l2cap_br_endpoint rx;
|
||||
struct bt_l2cap_br_endpoint rx;
|
||||
/** Channel Transmission Endpoint */
|
||||
struct bt_l2cap_br_endpoint tx;
|
||||
struct bt_l2cap_br_endpoint tx;
|
||||
/* For internal use only */
|
||||
atomic_t flags[1];
|
||||
atomic_t flags[1];
|
||||
|
||||
bt_l2cap_chan_state_t state;
|
||||
bt_l2cap_chan_state_t state;
|
||||
/** Remote PSM to be connected */
|
||||
uint16_t psm;
|
||||
uint16_t psm;
|
||||
/** Helps match request context during CoC */
|
||||
uint8_t ident;
|
||||
bt_security_t required_sec_level;
|
||||
uint8_t ident;
|
||||
bt_security_t required_sec_level;
|
||||
|
||||
/* Response Timeout eXpired (RTX) timer */
|
||||
struct k_work_delayable rtx_work;
|
||||
struct k_work_sync rtx_sync;
|
||||
struct k_work_delayable rtx_work;
|
||||
struct k_work_sync rtx_sync;
|
||||
|
||||
/** @internal To be used with @ref bt_conn.upper_data_ready */
|
||||
sys_snode_t _pdu_ready;
|
||||
sys_snode_t _pdu_ready;
|
||||
/** @internal To be used with @ref bt_conn.upper_data_ready */
|
||||
atomic_t _pdu_ready_lock;
|
||||
atomic_t _pdu_ready_lock;
|
||||
/** @internal Queue of net bufs not yet sent to lower layer */
|
||||
struct k_fifo _pdu_tx_queue;
|
||||
struct k_fifo _pdu_tx_queue;
|
||||
|
||||
#if defined(CONFIG_BT_L2CAP_RET_FC) || defined(__DOXYGEN__)
|
||||
/** @internal Total length of TX SDU */
|
||||
uint16_t _sdu_total_len;
|
||||
|
||||
/** @internal Holds the remaining length of current sending buffer */
|
||||
size_t _pdu_remaining;
|
||||
|
||||
/** @internal Holds the sending buffer. */
|
||||
struct net_buf *_pdu_buf;
|
||||
|
||||
/** @internal TX windows for outstanding frame */
|
||||
sys_slist_t _pdu_outstanding;
|
||||
|
||||
/** @internal PDU restore state */
|
||||
struct net_buf_simple_state _pdu_state;
|
||||
|
||||
/** @internal Free TX windows */
|
||||
struct k_fifo _free_tx_win;
|
||||
|
||||
/** @internal TX windows */
|
||||
struct bt_l2cap_br_window tx_win[CONFIG_BT_L2CAP_MAX_WINDOW_SIZE];
|
||||
|
||||
/** Segment SDU packet from upper layer */
|
||||
struct net_buf *_sdu;
|
||||
/** @internal RX SDU */
|
||||
uint16_t _sdu_len;
|
||||
#if defined(CONFIG_BT_L2CAP_SEG_RECV) || defined(__DOXYGEN__)
|
||||
uint16_t _sdu_len_done;
|
||||
#endif /* CONFIG_BT_L2CAP_SEG_RECV */
|
||||
/** @internal variables and sequence numbers */
|
||||
/** @internal The sending peer uses the following variables and sequence
|
||||
* numbers.
|
||||
*/
|
||||
/** @internal The send sequence number used to sequentially number each
|
||||
* new I-frame transmitted.
|
||||
*/
|
||||
uint16_t tx_seq;
|
||||
/** @internal The sequence number to be used in the next new I-frame
|
||||
* transmitted.
|
||||
*/
|
||||
uint16_t next_tx_seq;
|
||||
/** @internal The sequence number of the next I-frame expected to be
|
||||
* acknowledged by the receiving peer.
|
||||
*/
|
||||
uint16_t expected_ack_seq;
|
||||
/** @internal The receiving peer uses the following variables and sequence
|
||||
* numbers.
|
||||
*/
|
||||
/** @internal The sequence number sent in an acknowledgment frame to
|
||||
* request transmission of I-frame with TxSeq = ReqSeq and acknowledge
|
||||
* receipt of I-frames up to and including (ReqSeq-1).
|
||||
*/
|
||||
uint16_t req_seq;
|
||||
/** @internal The value of TxSeq expected in the next I-frame.
|
||||
*/
|
||||
uint16_t expected_tx_seq;
|
||||
/** @internal When segmented I-frames are buffered this is used to delay
|
||||
* acknowledgment of received I-frame so that new I-frame transmissions do
|
||||
* not cause buffer overflow.
|
||||
*/
|
||||
uint16_t buffer_seq;
|
||||
|
||||
/** @internal States of Enhanced Retransmission Mode */
|
||||
/** @internal Holds the number of times an S-frame operation is retried
|
||||
*/
|
||||
uint16_t retry_count;
|
||||
/** @internal save the ReqSeq of a SREJ frame */
|
||||
uint16_t srej_save_req_seq;
|
||||
|
||||
/** @internal Retransmission Timer */
|
||||
struct k_work_delayable ret_work;
|
||||
/** @internal Monitor Timer */
|
||||
struct k_work_delayable monitor_work;
|
||||
#endif /* CONFIG_BT_L2CAP_RET_FC */
|
||||
};
|
||||
|
||||
/** @brief L2CAP Channel operations structure.
|
||||
|
|
|
@ -13,6 +13,7 @@ config BT_CLASSIC
|
|||
select BT_CENTRAL
|
||||
select BT_SMP
|
||||
select BT_L2CAP_DYNAMIC_CHANNEL
|
||||
select CRC
|
||||
select EXPERIMENTAL
|
||||
help
|
||||
This option enables Bluetooth BR/EDR support
|
||||
|
@ -43,6 +44,85 @@ config BT_MAX_SCO_CONN
|
|||
Maximum number of simultaneous Bluetooth synchronous connections
|
||||
supported. The minimum (and default) number is 1.
|
||||
|
||||
config BT_L2CAP_RET
|
||||
bool "Bluetooth L2CAP retransmission mode [EXPERIMENTAL]"
|
||||
select EXPERIMENTAL
|
||||
help
|
||||
This option enables Bluetooth L2CAP retransmission mode
|
||||
|
||||
config BT_L2CAP_FC
|
||||
bool "Bluetooth L2CAP flow control mode [EXPERIMENTAL]"
|
||||
select EXPERIMENTAL
|
||||
help
|
||||
This option enables Bluetooth L2CAP flow control mode
|
||||
|
||||
config BT_L2CAP_ENH_RET
|
||||
bool "Bluetooth L2CAP enhance retransmission [EXPERIMENTAL]"
|
||||
select EXPERIMENTAL
|
||||
help
|
||||
This option enables Bluetooth L2CAP enhance retransmission
|
||||
|
||||
config BT_L2CAP_STREAM
|
||||
bool "Bluetooth L2CAP streaming mode [EXPERIMENTAL]"
|
||||
select EXPERIMENTAL
|
||||
help
|
||||
This option enables Bluetooth L2CAP streaming mode
|
||||
|
||||
config BT_L2CAP_RET_FC
|
||||
def_bool BT_L2CAP_RET || BT_L2CAP_FC || BT_L2CAP_ENH_RET || BT_L2CAP_STREAM
|
||||
|
||||
if BT_L2CAP_RET_FC
|
||||
config BT_L2CAP_FCS
|
||||
bool "Bluetooth L2CAP FCS Option [EXPERIMENTAL]"
|
||||
select EXPERIMENTAL
|
||||
depends on BT_L2CAP_STREAM || BT_L2CAP_ENH_RET
|
||||
help
|
||||
This option enables Bluetooth L2CAP FCS Option
|
||||
|
||||
config BT_L2CAP_EXT_WIN_SIZE
|
||||
bool "Bluetooth L2CAP Extended window size Option [EXPERIMENTAL]"
|
||||
select EXPERIMENTAL
|
||||
depends on BT_L2CAP_STREAM || BT_L2CAP_ENH_RET
|
||||
help
|
||||
This option enables Bluetooth L2CAP Extended window size Option
|
||||
|
||||
config BT_L2CAP_MPS
|
||||
int "Bluetooth L2CAP MPS for retransmission and Flow control"
|
||||
default 48
|
||||
range 48 BT_L2CAP_TX_MTU
|
||||
help
|
||||
Bluetooth L2CAP MPS for retransmission and Flow control
|
||||
|
||||
config BT_L2CAP_MAX_WINDOW_SIZE
|
||||
int "Maximum Windows Size of Retransmission and Flow Control"
|
||||
default 1
|
||||
range 1 32
|
||||
help
|
||||
Maximum Windows Size of Retransmission and Flow Control.
|
||||
The minimum (and default) number is 1.
|
||||
|
||||
config BT_L2CAP_BR_RET_TIMEOUT
|
||||
int "Retransmission timeout (milliseconds)"
|
||||
default 2000
|
||||
range 1000 2000
|
||||
help
|
||||
The Retransmission timeout shall be three times the value of flush timeout,
|
||||
subject to a minimum of 1000 milliseconds and maximum of 2000 milliseconds.
|
||||
|
||||
config BT_L2CAP_BR_MONITOR_TIMEOUT
|
||||
int "Monitor timeout (milliseconds)"
|
||||
default 12000 if BT_L2CAP_ENH_RET
|
||||
default BT_L2CAP_BR_RET_TIMEOUT
|
||||
range BT_L2CAP_BR_RET_TIMEOUT 12000
|
||||
help
|
||||
If a flush timeout exists on the link for Enhanced Retransmission mode and
|
||||
both sides of the link are configured to the same flush timeout value then the
|
||||
monitor timeout shall be set to a value at least as large as the Retransmission
|
||||
timeout otherwise the value of the Monitor timeout shall be six times the value
|
||||
of flush timeout, subject to a minimum of the retransmission timeout value and
|
||||
a maximum of 12000 milliseconds.
|
||||
endif # BT_L2CAP_RET_FC
|
||||
|
||||
config BT_RFCOMM
|
||||
bool "Bluetooth RFCOMM protocol support [EXPERIMENTAL]"
|
||||
select EXPERIMENTAL
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -70,3 +70,6 @@ struct bt_l2cap_chan *bt_l2cap_br_lookup_tx_cid(struct bt_conn *conn,
|
|||
|
||||
/* Get remote supported fixed channels */
|
||||
uint8_t bt_l2cap_br_get_remote_fixed_chan(struct bt_conn *conn);
|
||||
|
||||
/* L2CAP data receiving complete. */
|
||||
int bt_l2cap_br_chan_recv_complete(struct bt_l2cap_chan *chan);
|
||||
|
|
|
@ -134,11 +134,6 @@ struct bt_l2cap_conf_opt_qos {
|
|||
uint32_t delay_variation;
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_RET_FC_MODE_BASIC 0x00
|
||||
#define BT_L2CAP_RET_FC_MODE_RET 0x01
|
||||
#define BT_L2CAP_RET_FC_MODE_FC 0x02
|
||||
#define BT_L2CAP_RET_FC_MODE_ENH_RET 0x03
|
||||
#define BT_L2CAP_RET_FC_MODE_STREAM 0x04
|
||||
struct bt_l2cap_conf_opt_ret_fc {
|
||||
uint8_t mode;
|
||||
uint8_t tx_windows_size;
|
||||
|
@ -154,6 +149,19 @@ struct bt_l2cap_conf_opt_fcs {
|
|||
uint8_t type;
|
||||
} __packed;
|
||||
|
||||
struct bt_l2cap_conf_opt_ext_flow_spec {
|
||||
uint8_t identifier;
|
||||
uint8_t service_type;
|
||||
uint16_t sdu;
|
||||
uint32_t sdu_inter_arrival_time;
|
||||
uint32_t access_latency;
|
||||
uint32_t flush_timeout;
|
||||
} __packed;
|
||||
|
||||
struct bt_l2cap_conf_opt_ext_win_size {
|
||||
uint16_t max_windows_size;
|
||||
} __packed;
|
||||
|
||||
#define BT_L2CAP_DISCONN_REQ 0x06
|
||||
struct bt_l2cap_disconn_req {
|
||||
uint16_t dcid;
|
||||
|
@ -185,6 +193,188 @@ struct bt_l2cap_info_rsp {
|
|||
uint8_t data[0];
|
||||
} __packed;
|
||||
|
||||
/* I Frame Standard Control Field Format definition */
|
||||
#define BT_L2CAP_I_FRAME_STD_CONTROL_GET_TYPE(control) ((control) & 0x01)
|
||||
#define BT_L2CAP_I_FRAME_STD_CONTROL_GET_TX_SEQ(control) (((control) >> 0x01) & 0x3f)
|
||||
#define BT_L2CAP_I_FRAME_STD_CONTROL_GET_R(control) (((control) >> 0x07) & 0x01)
|
||||
#define BT_L2CAP_I_FRAME_STD_CONTROL_GET_REQ_SEQ(control) (((control) >> 0x08) & 0x3f)
|
||||
#define BT_L2CAP_I_FRAME_STD_CONTROL_GET_SAR(control) (((control) >> 0x0e) & 0x03)
|
||||
|
||||
#define BT_L2CAP_I_FRAME_STD_CONTROL_SET(tx_seq, r, req_seq, sar) \
|
||||
((((tx_seq) & 0x3f) << 0x01) | (((r) & 0x01) << 0x07) | (((req_seq) & 0x3f) << 0x08) | \
|
||||
(((sar) & 0x03) << 0x0e))
|
||||
|
||||
/* I Frame Enhanced Control Field Format definition */
|
||||
#define BT_L2CAP_I_FRAME_ENH_CONTROL_GET_TYPE(control) ((control) & 0x01)
|
||||
#define BT_L2CAP_I_FRAME_ENH_CONTROL_GET_TX_SEQ(control) (((control) >> 0x01) & 0x3f)
|
||||
#define BT_L2CAP_I_FRAME_ENH_CONTROL_GET_F(control) (((control) >> 0x07) & 0x01)
|
||||
#define BT_L2CAP_I_FRAME_ENH_CONTROL_GET_REQ_SEQ(control) (((control) >> 0x08) & 0x3f)
|
||||
#define BT_L2CAP_I_FRAME_ENH_CONTROL_GET_SAR(control) (((control) >> 0x0e) & 0x03)
|
||||
|
||||
#define BT_L2CAP_I_FRAME_ENH_CONTROL_SET(tx_seq, f, req_seq, sar) \
|
||||
((((tx_seq) & 0x3f) << 0x01) | (((f) & 0x01) << 0x07) | (((req_seq) & 0x3f) << 0x08) | \
|
||||
(((sar) & 0x03) << 0x0e))
|
||||
|
||||
/* I Frame Extended Control Field Format definition */
|
||||
#define BT_L2CAP_I_FRAME_EXT_CONTROL_GET_TYPE(control) ((control) & 0x01)
|
||||
#define BT_L2CAP_I_FRAME_EXT_CONTROL_GET_F(control) (((control) >> 0x01) & 0x01)
|
||||
#define BT_L2CAP_I_FRAME_EXT_CONTROL_GET_REQ_SEQ(control) (((control) >> 0x02) & 0x3fff)
|
||||
#define BT_L2CAP_I_FRAME_EXT_CONTROL_GET_SAR(control) (((control) >> 0x10) & 0x03)
|
||||
#define BT_L2CAP_I_FRAME_EXT_CONTROL_GET_TX_SEQ(control) (((control) >> 0x12) & 0x3fff)
|
||||
|
||||
#define BT_L2CAP_I_FRAME_EXT_CONTROL_SET(f, tx_seq, sar, req_seq) \
|
||||
((((f) & 0x01) << 0x01) | (((req_seq) & 0x3fff) << 0x02) | (((sar) & 0x03) << 0x10) | \
|
||||
(((tx_seq) & 0x3fff) << 0x12))
|
||||
|
||||
/* S Frame Standard Control Field Format definition */
|
||||
#define BT_L2CAP_S_FRAME_STD_CONTROL_GET_TYPE(control) ((control) & 0x01)
|
||||
#define BT_L2CAP_S_FRAME_STD_CONTROL_GET_S(control) (((control) >> 0x02) & 0x03)
|
||||
#define BT_L2CAP_S_FRAME_STD_CONTROL_GET_R(control) (((control) >> 0x07) & 0x01)
|
||||
#define BT_L2CAP_S_FRAME_STD_CONTROL_GET_REQ_SEQ(control) (((control) >> 0x08) & 0x3f)
|
||||
|
||||
#define BT_L2CAP_S_FRAME_STD_CONTROL_SET(s, r, req_seq) \
|
||||
(((1) & 0x01) | (((s) & 0x03) << 0x02) | (((r) & 0x01) << 0x07) | \
|
||||
(((req_seq) & 0x3f) << 0x08))
|
||||
|
||||
/* S Frame Enhanced Control Field Format definition */
|
||||
#define BT_L2CAP_S_FRAME_ENH_CONTROL_GET_TYPE(control) ((control) & 0x01)
|
||||
#define BT_L2CAP_S_FRAME_ENH_CONTROL_GET_S(control) (((control) >> 0x02) & 0x03)
|
||||
#define BT_L2CAP_S_FRAME_ENH_CONTROL_GET_P(control) (((control) >> 0x04) & 0x01)
|
||||
#define BT_L2CAP_S_FRAME_ENH_CONTROL_GET_F(control) (((control) >> 0x07) & 0x01)
|
||||
#define BT_L2CAP_S_FRAME_ENH_CONTROL_GET_REQ_SEQ(control) (((control) >> 0x08) & 0x3f)
|
||||
|
||||
#define BT_L2CAP_S_FRAME_ENH_CONTROL_SET(s, p, f, req_seq) \
|
||||
(((1) & 0x01) | (((s) & 0x03) << 0x02) | (((p) & 0x01) << 0x04) | (((f) & 0x01) << 0x07) | \
|
||||
(((req_seq) & 0x3f) << 0x08))
|
||||
|
||||
/* S Frame Extended Control Field Format definition */
|
||||
#define BT_L2CAP_S_FRAME_EXT_CONTROL_GET_TYPE(control) ((control) & 0x01)
|
||||
#define BT_L2CAP_S_FRAME_EXT_CONTROL_GET_F(control) (((control) >> 0x01) & 0x01)
|
||||
#define BT_L2CAP_S_FRAME_EXT_CONTROL_GET_REQ_SEQ(control) (((control) >> 0x02) & 0x3fff)
|
||||
#define BT_L2CAP_S_FRAME_EXT_CONTROL_GET_S(control) (((control) >> 0x10) & 0x03)
|
||||
#define BT_L2CAP_S_FRAME_EXT_CONTROL_GET_P(control) (((control) >> 0x12) & 0x01)
|
||||
|
||||
#define BT_L2CAP_S_FRAME_EXT_CONTROL_SET(f, req_seq, s, p) \
|
||||
(((1) & 0x01) | (((f) & 0x01) << 0x01) | (((req_seq) & 0x3fff) << 0x02) | \
|
||||
(((s) & 0x03) << 0x10) | (((p) & 0x01) << 0x12))
|
||||
|
||||
#define BT_L2CAP_CONTROL_TYPE_I 0x00
|
||||
#define BT_L2CAP_CONTROL_TYPE_S 0x01
|
||||
|
||||
#define BT_L2CAP_CONTROL_SEQ_MAX 0x40
|
||||
#define BT_L2CAP_EXT_CONTROL_SEQ_MAX 0x4000
|
||||
|
||||
#define BT_L2CAP_CONTROL_SAR_UNSEG 0x00
|
||||
#define BT_L2CAP_CONTROL_SAR_START 0x01
|
||||
#define BT_L2CAP_CONTROL_SAR_END 0x02
|
||||
#define BT_L2CAP_CONTROL_SAR_CONTI 0x03
|
||||
|
||||
#define BT_L2CAP_CONTROL_S_RR 0x00
|
||||
#define BT_L2CAP_CONTROL_S_REJ 0x01
|
||||
#define BT_L2CAP_CONTROL_S_RNR 0x02
|
||||
#define BT_L2CAP_CONTROL_S_SREJ 0x03
|
||||
|
||||
#define BT_L2CAP_RT_FC_SDU_LEN_SIZE 2
|
||||
|
||||
#define BT_L2CAP_STD_CONTROL_SIZE 2
|
||||
#define BT_L2CAP_ENH_CONTROL_SIZE 2
|
||||
#define BT_L2CAP_EXT_CONTROL_SIZE 4
|
||||
|
||||
#define BT_L2CAP_FCS_SIZE 2
|
||||
|
||||
#if defined(CONFIG_BT_L2CAP_RET_FC)
|
||||
/**
|
||||
*
|
||||
* @brief Helper to calculate L2CAP SDU header size.
|
||||
* Useful for creating buffer pools.
|
||||
*
|
||||
* @param mtu Required BT_L2CAP_*_SDU.
|
||||
*
|
||||
* @return Header size of the L2CAP channel.
|
||||
*/
|
||||
static inline size_t bt_l2cap_br_get_ret_fc_hdr_size(struct bt_l2cap_br_chan *chan)
|
||||
{
|
||||
if (chan->tx.mode != BT_L2CAP_BR_LINK_MODE_BASIC) {
|
||||
if (chan->tx.extended_control) {
|
||||
return BT_L2CAP_EXT_CONTROL_SIZE + BT_L2CAP_RT_FC_SDU_LEN_SIZE;
|
||||
} else {
|
||||
return BT_L2CAP_STD_CONTROL_SIZE + BT_L2CAP_RT_FC_SDU_LEN_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline size_t bt_l2cap_br_get_ret_fc_tail_size(struct bt_l2cap_br_chan *chan)
|
||||
{
|
||||
if (chan->tx.mode != BT_L2CAP_BR_LINK_MODE_BASIC) {
|
||||
if (chan->tx.fcs == BT_L2CAP_BR_FCS_16BIT) {
|
||||
return BT_L2CAP_FCS_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Helper to calculate L2CAP SDU header size.
|
||||
* Useful for creating buffer pools.
|
||||
*
|
||||
* @param chan the BR channel object point to `struct bt_l2cap_br_chan`.
|
||||
*
|
||||
* @return Header size of the L2CAP channel.
|
||||
*/
|
||||
#define BT_L2CAP_RT_FC_SDU_HDR_SIZE(chan) bt_l2cap_br_get_ret_fc_hdr_size(chan)
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Helper to calculate L2CAP SDU tail size.
|
||||
* Useful for creating buffer pools.
|
||||
*
|
||||
* @param chan the BR channel object point to `struct bt_l2cap_br_chan`.
|
||||
*
|
||||
* @return Header size of the L2CAP channel.
|
||||
*/
|
||||
#define BT_L2CAP_RT_FC_SDU_TAIL_SIZE(chan) bt_l2cap_br_get_ret_fc_tail_size(chan)
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Helper to calculate needed buffer size for L2CAP SDUs.
|
||||
* Useful for creating buffer pools.
|
||||
*
|
||||
* @param chan the BR channel object point to `struct bt_l2cap_br_chan`.
|
||||
* @param mtu Required BT_L2CAP_*_SDU.
|
||||
*
|
||||
* @return Needed buffer size to match the requested L2CAP SDU MTU.
|
||||
*/
|
||||
#define BT_L2CAP_RT_FC_SDU_BUF_SIZE(chan, mtu) \
|
||||
(BT_L2CAP_BUF_SIZE(BT_L2CAP_RT_FC_SDU_HDR_SIZE((chan)) + (mtu) + \
|
||||
BT_L2CAP_RT_FC_SDU_TAIL_SIZE((chan))))
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Helper to calculate needed buffer size for L2CAP SDUs.
|
||||
* Useful for creating buffer pools.
|
||||
*
|
||||
* @param mtu Required BT_L2CAP_*_SDU.
|
||||
*
|
||||
* @return Needed buffer size to match the requested L2CAP SDU MTU.
|
||||
*/
|
||||
#define BT_L2CAP_RT_FC_MAX_SDU_BUF_SIZE(mtu) \
|
||||
BT_L2CAP_BUF_SIZE((mtu) + BT_L2CAP_EXT_CONTROL_SIZE + BT_L2CAP_RT_FC_SDU_LEN_SIZE + \
|
||||
BT_L2CAP_FCS_SIZE)
|
||||
|
||||
/**
|
||||
* @brief Headroom needed for outgoing L2CAP PDUs if channel in one of
|
||||
* following mode, including retransmission, flow control, enhance
|
||||
* retransmission, and streaming.
|
||||
*
|
||||
* @param chan the BR channel object point to `struct bt_l2cap_br_chan`.
|
||||
*/
|
||||
#define BT_L2CAP_RET_FC_SDU_CHAN_SEND_RESERVE(chan) (BT_L2CAP_RT_FC_SDU_HDR_SIZE(chan))
|
||||
#endif /* CONFIG_BT_L2CAP_RET_FC */
|
||||
|
||||
#define BR_CHAN(_ch) CONTAINER_OF(_ch, struct bt_l2cap_br_chan, chan)
|
||||
|
||||
/* Add channel to the connection */
|
||||
|
|
|
@ -2417,6 +2417,10 @@ int bt_l2cap_chan_recv_complete(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
|||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CLASSIC) && conn->type == BT_CONN_TYPE_BR) {
|
||||
return bt_l2cap_br_chan_recv_complete(chan);
|
||||
}
|
||||
|
||||
if (conn->type != BT_CONN_TYPE_LE) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue