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)
|
#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. */
|
/** @brief BREDR L2CAP Endpoint structure. */
|
||||||
struct bt_l2cap_br_endpoint {
|
struct bt_l2cap_br_endpoint {
|
||||||
/** Endpoint Channel Identifier (CID) */
|
/** Endpoint Channel Identifier (CID) */
|
||||||
uint16_t cid;
|
uint16_t cid;
|
||||||
/** Endpoint Maximum Transmission Unit */
|
/** 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. */
|
/** @brief BREDR L2CAP Channel structure. */
|
||||||
struct bt_l2cap_br_chan {
|
struct bt_l2cap_br_chan {
|
||||||
/** Common L2CAP channel reference object */
|
/** Common L2CAP channel reference object */
|
||||||
struct bt_l2cap_chan chan;
|
struct bt_l2cap_chan chan;
|
||||||
/** Channel Receiving Endpoint */
|
/** Channel Receiving Endpoint */
|
||||||
struct bt_l2cap_br_endpoint rx;
|
struct bt_l2cap_br_endpoint rx;
|
||||||
/** Channel Transmission Endpoint */
|
/** Channel Transmission Endpoint */
|
||||||
struct bt_l2cap_br_endpoint tx;
|
struct bt_l2cap_br_endpoint tx;
|
||||||
/* For internal use only */
|
/* 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 */
|
/** Remote PSM to be connected */
|
||||||
uint16_t psm;
|
uint16_t psm;
|
||||||
/** Helps match request context during CoC */
|
/** Helps match request context during CoC */
|
||||||
uint8_t ident;
|
uint8_t ident;
|
||||||
bt_security_t required_sec_level;
|
bt_security_t required_sec_level;
|
||||||
|
|
||||||
/* Response Timeout eXpired (RTX) timer */
|
/* Response Timeout eXpired (RTX) timer */
|
||||||
struct k_work_delayable rtx_work;
|
struct k_work_delayable rtx_work;
|
||||||
struct k_work_sync rtx_sync;
|
struct k_work_sync rtx_sync;
|
||||||
|
|
||||||
/** @internal To be used with @ref bt_conn.upper_data_ready */
|
/** @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 */
|
/** @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 */
|
/** @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.
|
/** @brief L2CAP Channel operations structure.
|
||||||
|
|
|
@ -13,6 +13,7 @@ config BT_CLASSIC
|
||||||
select BT_CENTRAL
|
select BT_CENTRAL
|
||||||
select BT_SMP
|
select BT_SMP
|
||||||
select BT_L2CAP_DYNAMIC_CHANNEL
|
select BT_L2CAP_DYNAMIC_CHANNEL
|
||||||
|
select CRC
|
||||||
select EXPERIMENTAL
|
select EXPERIMENTAL
|
||||||
help
|
help
|
||||||
This option enables Bluetooth BR/EDR support
|
This option enables Bluetooth BR/EDR support
|
||||||
|
@ -43,6 +44,85 @@ config BT_MAX_SCO_CONN
|
||||||
Maximum number of simultaneous Bluetooth synchronous connections
|
Maximum number of simultaneous Bluetooth synchronous connections
|
||||||
supported. The minimum (and default) number is 1.
|
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
|
config BT_RFCOMM
|
||||||
bool "Bluetooth RFCOMM protocol support [EXPERIMENTAL]"
|
bool "Bluetooth RFCOMM protocol support [EXPERIMENTAL]"
|
||||||
select 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 */
|
/* Get remote supported fixed channels */
|
||||||
uint8_t bt_l2cap_br_get_remote_fixed_chan(struct bt_conn *conn);
|
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;
|
uint32_t delay_variation;
|
||||||
} __packed;
|
} __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 {
|
struct bt_l2cap_conf_opt_ret_fc {
|
||||||
uint8_t mode;
|
uint8_t mode;
|
||||||
uint8_t tx_windows_size;
|
uint8_t tx_windows_size;
|
||||||
|
@ -154,6 +149,19 @@ struct bt_l2cap_conf_opt_fcs {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
} __packed;
|
} __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
|
#define BT_L2CAP_DISCONN_REQ 0x06
|
||||||
struct bt_l2cap_disconn_req {
|
struct bt_l2cap_disconn_req {
|
||||||
uint16_t dcid;
|
uint16_t dcid;
|
||||||
|
@ -185,6 +193,188 @@ struct bt_l2cap_info_rsp {
|
||||||
uint8_t data[0];
|
uint8_t data[0];
|
||||||
} __packed;
|
} __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)
|
#define BR_CHAN(_ch) CONTAINER_OF(_ch, struct bt_l2cap_br_chan, chan)
|
||||||
|
|
||||||
/* Add channel to the connection */
|
/* 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;
|
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) {
|
if (conn->type != BT_CONN_TYPE_LE) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue