Bluetooth: EWS: rewrite handling SAR bits
Segmentation and Reassembly (SAR) occupies different windows in standard and extended control fields. Convert hardcoded masks to relative ones and use shift to access SAR bits. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
This commit is contained in:
parent
ab784b7383
commit
7e0ef6ee13
|
@ -146,10 +146,10 @@ struct l2cap_conninfo {
|
||||||
#define L2CAP_SUPER_SREJ 0x03
|
#define L2CAP_SUPER_SREJ 0x03
|
||||||
|
|
||||||
/* L2CAP Segmentation and Reassembly */
|
/* L2CAP Segmentation and Reassembly */
|
||||||
#define L2CAP_SDU_UNSEGMENTED 0x0000
|
#define L2CAP_SAR_UNSEGMENTED 0x00
|
||||||
#define L2CAP_SDU_START 0x4000
|
#define L2CAP_SAR_START 0x01
|
||||||
#define L2CAP_SDU_END 0x8000
|
#define L2CAP_SAR_END 0x02
|
||||||
#define L2CAP_SDU_CONTINUE 0xC000
|
#define L2CAP_SAR_CONTINUE 0x03
|
||||||
|
|
||||||
/* L2CAP Command rej. reasons */
|
/* L2CAP Command rej. reasons */
|
||||||
#define L2CAP_REJ_NOT_UNDERSTOOD 0x0000
|
#define L2CAP_REJ_NOT_UNDERSTOOD 0x0000
|
||||||
|
@ -516,7 +516,34 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
|
||||||
#define __get_reqseq(ctrl) (((ctrl) & L2CAP_CTRL_REQSEQ) >> 8)
|
#define __get_reqseq(ctrl) (((ctrl) & L2CAP_CTRL_REQSEQ) >> 8)
|
||||||
#define __is_iframe(ctrl) (!((ctrl) & L2CAP_CTRL_FRAME_TYPE))
|
#define __is_iframe(ctrl) (!((ctrl) & L2CAP_CTRL_FRAME_TYPE))
|
||||||
#define __is_sframe(ctrl) ((ctrl) & L2CAP_CTRL_FRAME_TYPE)
|
#define __is_sframe(ctrl) ((ctrl) & L2CAP_CTRL_FRAME_TYPE)
|
||||||
#define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
|
static inline __u8 __get_ctrl_sar(struct l2cap_chan *chan, __u32 ctrl)
|
||||||
|
{
|
||||||
|
if (test_bit(FLAG_EXT_CTRL, &chan->flags))
|
||||||
|
return (ctrl & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
|
||||||
|
else
|
||||||
|
return (ctrl & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __u32 __set_ctrl_sar(struct l2cap_chan *chan, __u32 sar)
|
||||||
|
{
|
||||||
|
if (test_bit(FLAG_EXT_CTRL, &chan->flags))
|
||||||
|
return (sar << L2CAP_EXT_CTRL_SAR_SHIFT) & L2CAP_EXT_CTRL_SAR;
|
||||||
|
else
|
||||||
|
return (sar << L2CAP_CTRL_SAR_SHIFT) & L2CAP_CTRL_SAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool __is_sar_start(struct l2cap_chan *chan, __u32 ctrl)
|
||||||
|
{
|
||||||
|
return __get_ctrl_sar(chan, ctrl) == L2CAP_SAR_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __u32 __get_sar_mask(struct l2cap_chan *chan)
|
||||||
|
{
|
||||||
|
if (test_bit(FLAG_EXT_CTRL, &chan->flags))
|
||||||
|
return L2CAP_EXT_CTRL_SAR;
|
||||||
|
else
|
||||||
|
return L2CAP_CTRL_SAR;
|
||||||
|
}
|
||||||
|
|
||||||
static inline __u8 __get_ctrl_super(struct l2cap_chan *chan, __u32 ctrl)
|
static inline __u8 __get_ctrl_super(struct l2cap_chan *chan, __u32 ctrl)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1311,7 +1311,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
|
||||||
tx_skb = skb_clone(skb, GFP_ATOMIC);
|
tx_skb = skb_clone(skb, GFP_ATOMIC);
|
||||||
bt_cb(skb)->retries++;
|
bt_cb(skb)->retries++;
|
||||||
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
|
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
|
||||||
control &= L2CAP_CTRL_SAR;
|
control &= __get_sar_mask(chan);
|
||||||
|
|
||||||
if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
|
if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
|
||||||
control |= L2CAP_CTRL_FINAL;
|
control |= L2CAP_CTRL_FINAL;
|
||||||
|
@ -1351,7 +1351,7 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
|
||||||
bt_cb(skb)->retries++;
|
bt_cb(skb)->retries++;
|
||||||
|
|
||||||
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
|
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
|
||||||
control &= L2CAP_CTRL_SAR;
|
control &= __get_sar_mask(chan);
|
||||||
|
|
||||||
if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
|
if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
|
||||||
control |= L2CAP_CTRL_FINAL;
|
control |= L2CAP_CTRL_FINAL;
|
||||||
|
@ -1582,7 +1582,7 @@ static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, si
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
|
||||||
skb_queue_head_init(&sar_queue);
|
skb_queue_head_init(&sar_queue);
|
||||||
control = L2CAP_SDU_START;
|
control = __set_ctrl_sar(chan, L2CAP_SAR_START);
|
||||||
skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
|
skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
|
||||||
if (IS_ERR(skb))
|
if (IS_ERR(skb))
|
||||||
return PTR_ERR(skb);
|
return PTR_ERR(skb);
|
||||||
|
@ -1595,10 +1595,10 @@ static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, si
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
|
|
||||||
if (len > chan->remote_mps) {
|
if (len > chan->remote_mps) {
|
||||||
control = L2CAP_SDU_CONTINUE;
|
control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
|
||||||
buflen = chan->remote_mps;
|
buflen = chan->remote_mps;
|
||||||
} else {
|
} else {
|
||||||
control = L2CAP_SDU_END;
|
control = __set_ctrl_sar(chan, L2CAP_SAR_END);
|
||||||
buflen = len;
|
buflen = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1654,7 +1654,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
|
||||||
case L2CAP_MODE_STREAMING:
|
case L2CAP_MODE_STREAMING:
|
||||||
/* Entire SDU fits into one PDU */
|
/* Entire SDU fits into one PDU */
|
||||||
if (len <= chan->remote_mps) {
|
if (len <= chan->remote_mps) {
|
||||||
control = L2CAP_SDU_UNSEGMENTED;
|
control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
|
||||||
skb = l2cap_create_iframe_pdu(chan, msg, len, control,
|
skb = l2cap_create_iframe_pdu(chan, msg, len, control,
|
||||||
0);
|
0);
|
||||||
if (IS_ERR(skb))
|
if (IS_ERR(skb))
|
||||||
|
@ -3201,15 +3201,15 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u1
|
||||||
{
|
{
|
||||||
int err = -EINVAL;
|
int err = -EINVAL;
|
||||||
|
|
||||||
switch (control & L2CAP_CTRL_SAR) {
|
switch (__get_ctrl_sar(chan, control)) {
|
||||||
case L2CAP_SDU_UNSEGMENTED:
|
case L2CAP_SAR_UNSEGMENTED:
|
||||||
if (chan->sdu)
|
if (chan->sdu)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
err = chan->ops->recv(chan->data, skb);
|
err = chan->ops->recv(chan->data, skb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L2CAP_SDU_START:
|
case L2CAP_SAR_START:
|
||||||
if (chan->sdu)
|
if (chan->sdu)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3231,7 +3231,7 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u1
|
||||||
err = 0;
|
err = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L2CAP_SDU_CONTINUE:
|
case L2CAP_SAR_CONTINUE:
|
||||||
if (!chan->sdu)
|
if (!chan->sdu)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3245,7 +3245,7 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u1
|
||||||
err = 0;
|
err = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L2CAP_SDU_END:
|
case L2CAP_SAR_END:
|
||||||
if (!chan->sdu)
|
if (!chan->sdu)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3343,7 +3343,7 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
skb = skb_dequeue(&chan->srej_q);
|
skb = skb_dequeue(&chan->srej_q);
|
||||||
control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
|
control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
|
||||||
err = l2cap_reassemble_sdu(chan, skb, control);
|
err = l2cap_reassemble_sdu(chan, skb, control);
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
@ -3398,7 +3398,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
|
||||||
{
|
{
|
||||||
u8 tx_seq = __get_txseq(rx_control);
|
u8 tx_seq = __get_txseq(rx_control);
|
||||||
u8 req_seq = __get_reqseq(rx_control);
|
u8 req_seq = __get_reqseq(rx_control);
|
||||||
u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
|
u8 sar = __get_ctrl_sar(chan, rx_control);
|
||||||
int tx_seq_offset, expected_tx_seq_offset;
|
int tx_seq_offset, expected_tx_seq_offset;
|
||||||
int num_to_ack = (chan->tx_win/6) + 1;
|
int num_to_ack = (chan->tx_win/6) + 1;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
@ -3707,7 +3707,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
|
||||||
if (l2cap_check_fcs(chan, skb))
|
if (l2cap_check_fcs(chan, skb))
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
if (__is_sar_start(control) && __is_iframe(control))
|
if (__is_sar_start(chan, control) && __is_iframe(control))
|
||||||
len -= 2;
|
len -= 2;
|
||||||
|
|
||||||
if (chan->fcs == L2CAP_FCS_CRC16)
|
if (chan->fcs == L2CAP_FCS_CRC16)
|
||||||
|
@ -3811,7 +3811,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
|
||||||
if (l2cap_check_fcs(chan, skb))
|
if (l2cap_check_fcs(chan, skb))
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
if (__is_sar_start(control))
|
if (__is_sar_start(chan, control))
|
||||||
len -= 2;
|
len -= 2;
|
||||||
|
|
||||||
if (chan->fcs == L2CAP_FCS_CRC16)
|
if (chan->fcs == L2CAP_FCS_CRC16)
|
||||||
|
|
Loading…
Reference in a new issue