From: Gustavo Padovan <padovan@profusion.mobi>
To: Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com>
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: [PATCHv1 2/5] Bluetooth: EWS: l2cap extended control field support
Date: Tue, 13 Sep 2011 23:48:09 -0300 [thread overview]
Message-ID: <20110914024808.GK16856@joana> (raw)
In-Reply-To: <1315404314-12045-3-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
* Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-09-07 17:05:11 +0300]:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> Adds support for parsing extended control field. Extended control
> field may be used for ERTM and streaming mode (if EWS specified).
> u32 control is used for standard, enhanced and extended control
> fields. Flag in l2cap chan specifies which format is in use.
>
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
> include/net/bluetooth/l2cap.h | 276 +++++++++++++++++++++++++++++++++------
> net/bluetooth/l2cap_core.c | 291 ++++++++++++++++++++++------------------
> 2 files changed, 397 insertions(+), 170 deletions(-)
>
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index 92eac16..5395984 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -27,6 +27,8 @@
> #ifndef __L2CAP_H
> #define __L2CAP_H
>
> +#include <asm/unaligned.h>
> +
> /* L2CAP defaults */
> #define L2CAP_DEFAULT_MTU 672
> #define L2CAP_DEFAULT_MIN_MTU 48
> @@ -113,36 +115,52 @@ struct l2cap_conninfo {
> #define L2CAP_FCS_CRC16 0x01
>
> /* L2CAP Control Field bit masks */
> -#define L2CAP_CTRL_SAR 0xC000
> -#define L2CAP_CTRL_REQSEQ 0x3F00
> -#define L2CAP_CTRL_TXSEQ 0x007E
> -#define L2CAP_CTRL_RETRANS 0x0080
> -#define L2CAP_CTRL_FINAL 0x0080
> -#define L2CAP_CTRL_POLL 0x0010
> -#define L2CAP_CTRL_SUPERVISE 0x000C
> -#define L2CAP_CTRL_FRAME_TYPE 0x0001 /* I- or S-Frame */
> -
> -#define L2CAP_CTRL_TXSEQ_SHIFT 1
> -#define L2CAP_CTRL_REQSEQ_SHIFT 8
> -#define L2CAP_CTRL_SAR_SHIFT 14
> +#define L2CAP_CTRL_SAR_MASK 0xC000
> +#define L2CAP_CTRL_REQSEQ_MASK 0x3F00
> +#define L2CAP_CTRL_TXSEQ_MASK 0x007E
> +#define L2CAP_CTRL_SUPERVISE_MASK 0x000C
Don't add a _MASK here. It just make the macros bigger.
> +
> +#define L2CAP_CTRL_RETRANS 0x0080
> +#define L2CAP_CTRL_FINAL 0x0080
> +#define L2CAP_CTRL_POLL 0x0010
> +#define L2CAP_CTRL_FRAME_TYPE 0x0001 /* I- or S-Frame */
> +
> +#define L2CAP_CTRL_TXSEQ_SHIFT 1
> +#define L2CAP_CTRL_SUPER_SHIFT 2
> +#define L2CAP_CTRL_REQSEQ_SHIFT 8
> +#define L2CAP_CTRL_SAR_SHIFT 14
> +
> +/* L2CAP Extended Control Field bit mask */
> +#define L2CAP_EXT_CTRL_TXSEQ_MASK 0xFFFC0000
> +#define L2CAP_EXT_CTRL_SAR_MASK 0x00030000
> +#define L2CAP_EXT_CTRL_SUPERVISE_MASK 0x00030000
> +#define L2CAP_EXT_CTRL_REQSEQ_MASK 0x0000FFFC
> +
> +#define L2CAP_EXT_CTRL_POLL 0x00040000
> +#define L2CAP_EXT_CTRL_FINAL 0x00000002
> +#define L2CAP_EXT_CTRL_FRAME_TYPE 0x00000001 /* I- or S-Frame */
> +
> +#define L2CAP_EXT_CTRL_REQSEQ_SHIFT 2
> +#define L2CAP_EXT_CTRL_SAR_SHIFT 16
> +#define L2CAP_EXT_CTRL_SUPER_SHIFT 16
> +#define L2CAP_EXT_CTRL_TXSEQ_SHIFT 18
>
> /* L2CAP Supervisory Function */
> -#define L2CAP_SUPER_RCV_READY 0x0000
> -#define L2CAP_SUPER_REJECT 0x0004
> -#define L2CAP_SUPER_RCV_NOT_READY 0x0008
> -#define L2CAP_SUPER_SELECT_REJECT 0x000C
> +#define L2CAP_SUPER_RR 0x00
> +#define L2CAP_SUPER_REJ 0x01
> +#define L2CAP_SUPER_RNR 0x02
> +#define L2CAP_SUPER_SREJ 0x03
>
> /* L2CAP Segmentation and Reassembly */
> -#define L2CAP_SDU_UNSEGMENTED 0x0000
> -#define L2CAP_SDU_START 0x4000
> -#define L2CAP_SDU_END 0x8000
> -#define L2CAP_SDU_CONTINUE 0xC000
> +#define L2CAP_SAR_UNSEGMENTED 0x00
> +#define L2CAP_SAR_START 0x01
> +#define L2CAP_SAR_END 0x02
> +#define L2CAP_SAR_CONTINUE 0x03
>
> /* L2CAP Command rej. reasons */
> -#define L2CAP_REJ_NOT_UNDERSTOOD 0x0000
> -#define L2CAP_REJ_MTU_EXCEEDED 0x0001
> -#define L2CAP_REJ_INVALID_CID 0x0002
> -
> +#define L2CAP_REJ_NOT_UNDERSTOOD 0x0000
> +#define L2CAP_REJ_MTU_EXCEEDED 0x0001
> +#define L2CAP_REJ_INVALID_CID 0x0002
>
> /* L2CAP structures */
> struct l2cap_hdr {
> @@ -150,6 +168,11 @@ struct l2cap_hdr {
> __le16 cid;
> } __packed;
> #define L2CAP_HDR_SIZE 4
> +#define L2CAP_ENHANCED_HDR_SIZE 6
> +#define L2CAP_EXTENDED_HDR_SIZE 8
> +
> +#define L2CAP_FCS_SIZE 2
> +#define L2CAP_SDULEN_SIZE 2
>
> struct l2cap_cmd_hdr {
> __u8 code;
> @@ -320,7 +343,7 @@ struct l2cap_conn_param_update_rsp {
>
> /* ----- L2CAP channels and connections ----- */
> struct srej_list {
> - __u8 tx_seq;
> + __u16 tx_seq;
> struct list_head list;
> };
>
> @@ -370,16 +393,16 @@ struct l2cap_chan {
> unsigned long conn_state;
> unsigned long flags;
>
> - __u8 next_tx_seq;
> - __u8 expected_ack_seq;
> - __u8 expected_tx_seq;
> - __u8 buffer_seq;
> - __u8 buffer_seq_srej;
> - __u8 srej_save_reqseq;
> - __u8 frames_sent;
> - __u8 unacked_frames;
> + __u16 next_tx_seq;
> + __u16 expected_ack_seq;
> + __u16 expected_tx_seq;
> + __u16 buffer_seq;
> + __u16 buffer_seq_srej;
> + __u16 srej_save_reqseq;
> + __u16 frames_sent;
> + __u16 unacked_frames;
> __u8 retry_count;
> - __u8 num_acked;
> + __u16 num_acked;
> __u16 sdu_len;
> struct sk_buff *sdu;
> struct sk_buff *sdu_last_frag;
> @@ -539,11 +562,186 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
> return sub == ch->remote_tx_win;
> }
>
> -#define __get_txseq(ctrl) (((ctrl) & L2CAP_CTRL_TXSEQ) >> 1)
> -#define __get_reqseq(ctrl) (((ctrl) & L2CAP_CTRL_REQSEQ) >> 8)
> -#define __is_iframe(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 __u16 __get_reqseq(struct l2cap_chan *chan, __u32 ctrl)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return (ctrl & L2CAP_EXT_CTRL_REQSEQ_MASK) >>
> + L2CAP_EXT_CTRL_REQSEQ_SHIFT;
> + else
> + return (ctrl & L2CAP_CTRL_REQSEQ_MASK) >>
> + L2CAP_CTRL_REQSEQ_SHIFT;
> +}
> +
> +static inline __u32 __set_reqseq(struct l2cap_chan *chan, __u32 reqseq)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return (reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT) &
> + L2CAP_EXT_CTRL_REQSEQ_MASK;
> + else
> + return (reqseq << L2CAP_CTRL_REQSEQ_SHIFT) &
> + L2CAP_CTRL_REQSEQ_MASK;
> +}
> +
> +static inline __u16 __get_txseq(struct l2cap_chan *chan, __u32 ctrl)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return (ctrl & L2CAP_EXT_CTRL_TXSEQ_MASK) >>
> + L2CAP_EXT_CTRL_TXSEQ_SHIFT;
> + else
> + return (ctrl & L2CAP_CTRL_TXSEQ_MASK) >>
> + L2CAP_CTRL_TXSEQ_SHIFT;
> +}
> +
> +static inline __u32 __set_txseq(struct l2cap_chan *chan, __u32 txseq)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return (txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT) &
> + L2CAP_EXT_CTRL_TXSEQ_MASK;
> + else
> + return (txseq << L2CAP_CTRL_TXSEQ_SHIFT) &
> + L2CAP_CTRL_TXSEQ_MASK;
> +}
> +
> +static inline bool __is_sframe(struct l2cap_chan *chan, __u32 ctrl)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return ctrl & L2CAP_EXT_CTRL_FRAME_TYPE;
> + else
> + return ctrl & L2CAP_CTRL_FRAME_TYPE;
> +}
> +
> +static inline __u32 __set_sframe(struct l2cap_chan *chan)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return L2CAP_EXT_CTRL_FRAME_TYPE;
> + else
> + return L2CAP_CTRL_FRAME_TYPE;
> +}
> +
> +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_MASK) >>
> + L2CAP_EXT_CTRL_SAR_SHIFT;
> + else
> + return (ctrl & L2CAP_CTRL_SAR_MASK) >>
> + 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_MASK;
> + else
> + return (sar << L2CAP_CTRL_SAR_SHIFT) &
> + L2CAP_CTRL_SAR_MASK;
> +}
> +
> +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_MASK;
> + else
> + return L2CAP_CTRL_SAR_MASK;
> +}
> +
> +static inline __u8 __get_ctrl_super(struct l2cap_chan *chan, __u32 ctrl)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return (ctrl & L2CAP_EXT_CTRL_SUPERVISE_MASK) >>
> + L2CAP_EXT_CTRL_SUPER_SHIFT;
> + else
> + return (ctrl & L2CAP_CTRL_SUPERVISE_MASK) >>
> + L2CAP_CTRL_SUPER_SHIFT;
> +}
> +
> +static inline __u32 __set_ctrl_super(struct l2cap_chan *chan, __u32 super)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return (super << L2CAP_EXT_CTRL_SUPER_SHIFT) &
> + L2CAP_EXT_CTRL_SUPERVISE_MASK;
> + else
> + return (super << L2CAP_CTRL_SUPER_SHIFT) &
> + L2CAP_CTRL_SUPERVISE_MASK;
> +}
> +
> +static inline __u32 __set_ctrl_final(struct l2cap_chan *chan)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return L2CAP_EXT_CTRL_FINAL;
> + else
> + return L2CAP_CTRL_FINAL;
> +}
> +
> +static inline bool __is_ctrl_final(struct l2cap_chan *chan, __u32 ctrl)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return ctrl & L2CAP_EXT_CTRL_FINAL;
> + else
> + return ctrl & L2CAP_CTRL_FINAL;
> +}
> +
> +static inline __u32 __set_ctrl_poll(struct l2cap_chan *chan)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return L2CAP_EXT_CTRL_POLL;
> + else
> + return L2CAP_CTRL_POLL;
> +}
> +
> +static inline bool __is_ctrl_poll(struct l2cap_chan *chan, __u32 ctrl)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return ctrl & L2CAP_EXT_CTRL_POLL;
> + else
> + return ctrl & L2CAP_CTRL_POLL;
> +}
> +
> +static inline __u32 __get_control(struct l2cap_chan *chan, void *p)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return get_unaligned_le32(p);
> + else
> + return get_unaligned_le16(p);
> +}
> +
> +static inline __u32 __get_control_pull(struct l2cap_chan *chan,
> + struct sk_buff *skb, void *p)
> +{
> + __u32 ctrl;
> +
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
> + ctrl = get_unaligned_le32(p);
> + skb_pull(skb, 4);
> + } else {
> + ctrl = get_unaligned_le16(p);
> + skb_pull(skb, 2);
> + }
> +
> + return ctrl;
> +}
> +
> +static inline void __put_control(struct l2cap_chan *chan, __u32 control, void *p)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return put_unaligned_le32(control, p);
> + else
> + return put_unaligned_le16(control, p);
> +}
> +
> +static inline void __put_control_put(struct l2cap_chan *chan, __u32 control, void *p)
> +{
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + return put_unaligned_le32(control, skb_put(p, 4));
> + else
> + return put_unaligned_le16(control, skb_put(p, 2));
> +}
>
> extern int disable_ertm;
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 81b8d02..aae92df 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -570,30 +570,36 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
> hci_send_acl(conn->hcon, skb, flags);
> }
>
> -static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
> +static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
> {
> struct sk_buff *skb;
> struct l2cap_hdr *lh;
> struct l2cap_conn *conn = chan->conn;
> - int count, hlen = L2CAP_HDR_SIZE + 2;
> + int count, hlen;
> u8 flags;
>
> if (chan->state != BT_CONNECTED)
> return;
>
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + hlen = L2CAP_EXTENDED_HDR_SIZE;
> + else
> + hlen = L2CAP_ENHANCED_HDR_SIZE;
> +
> if (chan->fcs == L2CAP_FCS_CRC16)
> hlen += 2;
>
> - BT_DBG("chan %p, control 0x%2.2x", chan, control);
> + BT_DBG("chan %p, control 0x%8.8x", chan, control);
>
> count = min_t(unsigned int, conn->mtu, hlen);
> - control |= L2CAP_CTRL_FRAME_TYPE;
> +
> + control |= __set_sframe(chan);
>
> if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
> - control |= L2CAP_CTRL_FINAL;
> + control |= __set_ctrl_final(chan);
>
> if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
> - control |= L2CAP_CTRL_POLL;
> + control |= __set_ctrl_poll(chan);
>
> skb = bt_skb_alloc(count, GFP_ATOMIC);
> if (!skb)
> @@ -602,7 +608,8 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
> lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
> lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
> lh->cid = cpu_to_le16(chan->dcid);
> - put_unaligned_le16(control, skb_put(skb, 2));
> +
> + __put_control_put(chan, control, skb);
>
> if (chan->fcs == L2CAP_FCS_CRC16) {
> u16 fcs = crc16(0, (u8 *)lh, count - 2);
> @@ -619,15 +626,15 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
> hci_send_acl(chan->conn->hcon, skb, flags);
> }
>
> -static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
> +static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
> {
> if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
> - control |= L2CAP_SUPER_RCV_NOT_READY;
> + control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
> set_bit(CONN_RNR_SENT, &chan->conn_state);
> } else
> - control |= L2CAP_SUPER_RCV_READY;
> + control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
>
> - control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
> + control |= __set_reqseq(chan, chan->buffer_seq);
>
> l2cap_send_sframe(chan, control);
> }
> @@ -1274,12 +1281,13 @@ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
> static void l2cap_streaming_send(struct l2cap_chan *chan)
> {
> struct sk_buff *skb;
> - u16 control, fcs;
> + u32 control;
> + u16 fcs;
>
> while ((skb = skb_dequeue(&chan->tx_q))) {
> - control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
> - control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
> - put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
> + control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
> + control |= __set_txseq(chan, chan->next_tx_seq);
> + __put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
>
> if (chan->fcs == L2CAP_FCS_CRC16) {
> fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
> @@ -1292,10 +1300,11 @@ static void l2cap_streaming_send(struct l2cap_chan *chan)
> }
> }
>
> -static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
> +static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
> {
> struct sk_buff *skb, *tx_skb;
> - u16 control, fcs;
> + u16 fcs;
> + u32 control;
>
> skb = skb_peek(&chan->tx_q);
> if (!skb)
> @@ -1318,16 +1327,17 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
>
> tx_skb = skb_clone(skb, GFP_ATOMIC);
> bt_cb(skb)->retries++;
> - control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
> - control &= L2CAP_CTRL_SAR;
> +
> + control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
> + control &= __get_sar_mask(chan);
>
> if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
> - control |= L2CAP_CTRL_FINAL;
> + control |= __set_ctrl_final(chan);
>
> - control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
> - | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
> + control |= __set_reqseq(chan, chan->buffer_seq);
> + control |= __set_txseq(chan, tx_seq);
>
> - put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
> + __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
>
> if (chan->fcs == L2CAP_FCS_CRC16) {
> fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
> @@ -1340,7 +1350,8 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
> static int l2cap_ertm_send(struct l2cap_chan *chan)
> {
> struct sk_buff *skb, *tx_skb;
> - u16 control, fcs;
> + u16 fcs;
> + u32 control;
> int nsent = 0;
>
> if (chan->state != BT_CONNECTED)
> @@ -1358,16 +1369,16 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
>
> bt_cb(skb)->retries++;
>
> - control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
> - control &= L2CAP_CTRL_SAR;
> + control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
> + control &= __get_sar_mask(chan);
>
> if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
> - control |= L2CAP_CTRL_FINAL;
> + control |= __set_ctrl_final(chan);
>
> - control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
> - | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
> - put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
> + control |= __set_reqseq(chan, chan->buffer_seq);
> + control |= __set_txseq(chan, chan->next_tx_seq);
>
> + __put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
>
> if (chan->fcs == L2CAP_FCS_CRC16) {
> fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
> @@ -1411,12 +1422,12 @@ static int l2cap_retransmit_frames(struct l2cap_chan *chan)
>
> static void l2cap_send_ack(struct l2cap_chan *chan)
> {
> - u16 control = 0;
> + u32 control = 0;
>
> - control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
> + control |= __set_reqseq(chan, chan->buffer_seq);
>
> if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
> - control |= L2CAP_SUPER_RCV_NOT_READY;
> + control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
> set_bit(CONN_RNR_SENT, &chan->conn_state);
> l2cap_send_sframe(chan, control);
> return;
> @@ -1425,20 +1436,20 @@ static void l2cap_send_ack(struct l2cap_chan *chan)
> if (l2cap_ertm_send(chan) > 0)
> return;
>
> - control |= L2CAP_SUPER_RCV_READY;
> + control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
> l2cap_send_sframe(chan, control);
> }
>
> static void l2cap_send_srejtail(struct l2cap_chan *chan)
> {
> struct srej_list *tail;
> - u16 control;
> + u32 control;
>
> - control = L2CAP_SUPER_SELECT_REJECT;
> - control |= L2CAP_CTRL_FINAL;
> + control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
> + control |= __set_ctrl_final(chan);
>
> tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
> - control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
> + control |= __set_reqseq(chan, tail->tx_seq);
>
> l2cap_send_sframe(chan, control);
> }
> @@ -1534,12 +1545,12 @@ static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct ms
> return skb;
> }
>
> -static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
> +static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u32 control, u16 sdulen)
> {
> struct sock *sk = chan->sk;
> struct l2cap_conn *conn = chan->conn;
> struct sk_buff *skb;
> - int err, count, hlen = L2CAP_HDR_SIZE + 2;
> + int err, count, hlen;
> struct l2cap_hdr *lh;
>
> BT_DBG("sk %p len %d", sk, (int)len);
> @@ -1547,6 +1558,11 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct m
> if (!conn)
> return ERR_PTR(-ENOTCONN);
>
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + hlen = L2CAP_EXTENDED_HDR_SIZE;
> + else
> + hlen = L2CAP_ENHANCED_HDR_SIZE;
> +
> if (sdulen)
> hlen += 2;
>
> @@ -1563,7 +1579,9 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct m
> lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
> lh->cid = cpu_to_le16(chan->dcid);
> lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
> - put_unaligned_le16(control, skb_put(skb, 2));
> +
> + __put_control_put(chan, control, skb);
> +
> if (sdulen)
> put_unaligned_le16(sdulen, skb_put(skb, 2));
>
> @@ -1584,11 +1602,11 @@ static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, si
> {
> struct sk_buff *skb;
> struct sk_buff_head sar_queue;
> - u16 control;
> + u32 control;
> size_t size = 0;
>
> 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);
> if (IS_ERR(skb))
> return PTR_ERR(skb);
> @@ -1601,10 +1619,10 @@ static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, si
> size_t buflen;
>
> if (len > chan->remote_mps) {
> - control = L2CAP_SDU_CONTINUE;
> + control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
> buflen = chan->remote_mps;
> } else {
> - control = L2CAP_SDU_END;
> + control = __set_ctrl_sar(chan, L2CAP_SAR_END);
> buflen = len;
> }
>
> @@ -1628,7 +1646,7 @@ static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, si
> int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
> {
> struct sk_buff *skb;
> - u16 control;
> + u32 control;
> int err;
>
> /* Connectionless channel */
> @@ -1660,7 +1678,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
> case L2CAP_MODE_STREAMING:
> /* Entire SDU fits into one PDU */
> 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,
> 0);
> if (IS_ERR(skb))
> @@ -1991,8 +2009,11 @@ done:
> rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
>
> l2cap_txwin_setup(chan);
> - rfc.txwin_size = chan->tx_win > L2CAP_DEFAULT_MAX_TX_WINDOW ?
> - L2CAP_DEFAULT_MAX_TX_WINDOW : chan->tx_win;
> +
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + rfc.txwin_size = L2CAP_DEFAULT_MAX_TX_WINDOW;
> + else
> + rfc.txwin_size = chan->tx_win;
>
> l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
> (unsigned long) &rfc);
> @@ -3267,7 +3288,12 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
> static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
> {
> u16 our_fcs, rcv_fcs;
> - int hdr_size = L2CAP_HDR_SIZE + 2;
> + int hdr_size;
> +
> + if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> + hdr_size = L2CAP_EXTENDED_HDR_SIZE;
> + else
> + hdr_size = L2CAP_ENHANCED_HDR_SIZE;
>
> if (chan->fcs == L2CAP_FCS_CRC16) {
> skb_trim(skb, skb->len - 2);
> @@ -3282,14 +3308,14 @@ static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
>
> static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
> {
> - u16 control = 0;
> + u32 control = 0;
>
> chan->frames_sent = 0;
>
> - control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
> + control |= __set_reqseq(chan, chan->buffer_seq);
>
> if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
> - control |= L2CAP_SUPER_RCV_NOT_READY;
> + control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
> l2cap_send_sframe(chan, control);
> set_bit(CONN_RNR_SENT, &chan->conn_state);
> }
> @@ -3301,12 +3327,12 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
>
> if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
> chan->frames_sent == 0) {
> - control |= L2CAP_SUPER_RCV_READY;
> + control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
> l2cap_send_sframe(chan, control);
> }
> }
>
> -static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
> +static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
> {
> struct sk_buff *next_skb;
> int tx_seq_offset, next_tx_seq_offset;
> @@ -3367,19 +3393,19 @@ static void append_skb_frag(struct sk_buff *skb,
> skb->truesize += new_frag->truesize;
> }
>
> -static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
> +static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
> {
> int err = -EINVAL;
>
> - switch (control & L2CAP_CTRL_SAR) {
> - case L2CAP_SDU_UNSEGMENTED:
> + switch (__get_ctrl_sar(chan, control)) {
> + case L2CAP_SAR_UNSEGMENTED:
> if (chan->sdu)
> break;
>
> err = chan->ops->recv(chan->data, skb);
> break;
>
> - case L2CAP_SDU_START:
> + case L2CAP_SAR_START:
> if (chan->sdu)
> break;
>
> @@ -3401,7 +3427,7 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u1
> err = 0;
> break;
>
> - case L2CAP_SDU_CONTINUE:
> + case L2CAP_SAR_CONTINUE:
> if (!chan->sdu)
> break;
>
> @@ -3415,7 +3441,7 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u1
> err = 0;
> break;
>
> - case L2CAP_SDU_END:
> + case L2CAP_SAR_END:
> if (!chan->sdu)
> break;
>
> @@ -3450,14 +3476,14 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u1
>
> static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
> {
> - u16 control;
> + u32 control;
>
> BT_DBG("chan %p, Enter local busy", chan);
>
> set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
>
> - control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
> - control |= L2CAP_SUPER_RCV_NOT_READY;
> + control = __set_reqseq(chan, chan->buffer_seq);
> + control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
> l2cap_send_sframe(chan, control);
>
> set_bit(CONN_RNR_SENT, &chan->conn_state);
> @@ -3467,13 +3493,14 @@ static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
>
> static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
> {
> - u16 control;
> + u32 control;
>
> if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
> goto done;
>
> - control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
> - control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
> + control = __set_reqseq(chan, chan->buffer_seq);
> + control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
> + control |= __set_ctrl_poll(chan);
> l2cap_send_sframe(chan, control);
> chan->retry_count = 1;
>
> @@ -3499,10 +3526,10 @@ void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
> }
> }
>
> -static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
> +static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
> {
> struct sk_buff *skb;
> - u16 control;
> + u32 control;
>
> while ((skb = skb_peek(&chan->srej_q)) &&
> !test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
> @@ -3512,7 +3539,7 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
> break;
>
> 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);
>
> if (err < 0) {
> @@ -3526,10 +3553,10 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
> }
> }
>
> -static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
> +static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
> {
> struct srej_list *l, *tmp;
> - u16 control;
> + u32 control;
>
> list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
> if (l->tx_seq == tx_seq) {
> @@ -3537,22 +3564,22 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
> kfree(l);
> return;
> }
> - control = L2CAP_SUPER_SELECT_REJECT;
> - control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
> + control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
> + control |= __set_reqseq(chan, l->tx_seq);
> l2cap_send_sframe(chan, control);
> list_del(&l->list);
> list_add_tail(&l->list, &chan->srej_l);
> }
> }
>
> -static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
> +static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
> {
> struct srej_list *new;
> - u16 control;
> + u32 control;
>
> while (tx_seq != chan->expected_tx_seq) {
> - control = L2CAP_SUPER_SELECT_REJECT;
> - control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
> + control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
> + control |= __set_reqseq(chan, chan->expected_tx_seq);
> l2cap_send_sframe(chan, control);
>
> new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
> @@ -3563,19 +3590,19 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
> chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
> }
>
> -static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
> +static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
> {
> - u8 tx_seq = __get_txseq(rx_control);
> - u8 req_seq = __get_reqseq(rx_control);
> - u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
> + u16 tx_seq = __get_txseq(chan, rx_control);
> + u16 req_seq = __get_reqseq(chan, rx_control);
> + u8 sar = __get_ctrl_sar(chan, rx_control);
> int tx_seq_offset, expected_tx_seq_offset;
> int num_to_ack = (chan->tx_win/6) + 1;
> int err = 0;
>
> - BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
> + BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
> tx_seq, rx_control);
>
> - if (L2CAP_CTRL_FINAL & rx_control &&
> + if (__is_ctrl_final(chan, rx_control) &&
> test_bit(CONN_WAIT_F, &chan->conn_state)) {
> __clear_monitor_timer(chan);
> if (chan->unacked_frames > 0)
> @@ -3680,7 +3707,7 @@ expected:
> return err;
> }
>
> - if (rx_control & L2CAP_CTRL_FINAL) {
> + if (__is_ctrl_final(chan, rx_control)) {
> if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
> l2cap_retransmit_frames(chan);
> }
> @@ -3698,15 +3725,16 @@ drop:
> return 0;
> }
>
> -static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
> +static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
> {
> - BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
> - rx_control);
> + BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x",
> + chan, __get_reqseq(chan, rx_control),
> + rx_control);
Indentation is wrong here.
>
> - chan->expected_ack_seq = __get_reqseq(rx_control);
> + chan->expected_ack_seq = __get_reqseq(chan, rx_control);
> l2cap_drop_acked_frames(chan);
>
> - if (rx_control & L2CAP_CTRL_POLL) {
> + if (__is_ctrl_poll(chan, rx_control)) {
> set_bit(CONN_SEND_FBIT, &chan->conn_state);
> if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
> if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
> @@ -3719,7 +3747,7 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co
> l2cap_send_i_or_rr_or_rnr(chan);
> }
>
> - } else if (rx_control & L2CAP_CTRL_FINAL) {
> + } else if (__is_ctrl_final(chan, rx_control)) {
> clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
>
> if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
> @@ -3738,9 +3766,9 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co
> }
> }
>
> -static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
> +static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
> {
> - u8 tx_seq = __get_reqseq(rx_control);
> + u16 tx_seq = __get_reqseq(chan, rx_control);
>
> BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
>
> @@ -3749,7 +3777,7 @@ static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_c
> chan->expected_ack_seq = tx_seq;
> l2cap_drop_acked_frames(chan);
>
> - if (rx_control & L2CAP_CTRL_FINAL) {
> + if (__is_ctrl_final(chan, rx_control)) {
> if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
> l2cap_retransmit_frames(chan);
> } else {
> @@ -3759,15 +3787,15 @@ static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_c
> set_bit(CONN_REJ_ACT, &chan->conn_state);
> }
> }
> -static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
> +static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
> {
> - u8 tx_seq = __get_reqseq(rx_control);
> + u16 tx_seq = __get_reqseq(chan, rx_control);
>
> - BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
> + BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
>
> clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
>
> - if (rx_control & L2CAP_CTRL_POLL) {
> + if (__is_ctrl_poll(chan, rx_control)) {
> chan->expected_ack_seq = tx_seq;
> l2cap_drop_acked_frames(chan);
>
> @@ -3780,7 +3808,7 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_
> chan->srej_save_reqseq = tx_seq;
> set_bit(CONN_SREJ_ACT, &chan->conn_state);
> }
> - } else if (rx_control & L2CAP_CTRL_FINAL) {
> + } else if (__is_ctrl_final(chan, rx_control)) {
> if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
> chan->srej_save_reqseq == tx_seq)
> clear_bit(CONN_SREJ_ACT, &chan->conn_state);
> @@ -3795,37 +3823,39 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_
> }
> }
>
> -static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
> +static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
> {
> - u8 tx_seq = __get_reqseq(rx_control);
> + u16 tx_seq = __get_reqseq(chan, rx_control);
>
> - BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
> + BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
>
> set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
> chan->expected_ack_seq = tx_seq;
> l2cap_drop_acked_frames(chan);
>
> - if (rx_control & L2CAP_CTRL_POLL)
> + if (__is_ctrl_poll(chan, rx_control))
> set_bit(CONN_SEND_FBIT, &chan->conn_state);
>
> if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
> __clear_retrans_timer(chan);
> - if (rx_control & L2CAP_CTRL_POLL)
> + if (__is_ctrl_poll(chan, rx_control))
> l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
> return;
> }
>
> - if (rx_control & L2CAP_CTRL_POLL)
> + if (__is_ctrl_poll(chan, rx_control))
> l2cap_send_srejtail(chan);
> - else
> - l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
> + else {
> + rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
> + l2cap_send_sframe(chan, rx_control);
> + }
You need to add { } to th if as well.
> }
>
> -static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
> +static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
> {
> - BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
> + BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
>
> - if (L2CAP_CTRL_FINAL & rx_control &&
> + if (__is_ctrl_final(chan, rx_control) &&
> test_bit(CONN_WAIT_F, &chan->conn_state)) {
> __clear_monitor_timer(chan);
> if (chan->unacked_frames > 0)
> @@ -3833,20 +3863,20 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont
> clear_bit(CONN_WAIT_F, &chan->conn_state);
> }
>
> - switch (rx_control & L2CAP_CTRL_SUPERVISE) {
> - case L2CAP_SUPER_RCV_READY:
> + switch (__get_ctrl_super(chan, rx_control)) {
> + case L2CAP_SUPER_RR:
> l2cap_data_channel_rrframe(chan, rx_control);
> break;
>
> - case L2CAP_SUPER_REJECT:
> + case L2CAP_SUPER_REJ:
> l2cap_data_channel_rejframe(chan, rx_control);
> break;
>
> - case L2CAP_SUPER_SELECT_REJECT:
> + case L2CAP_SUPER_SREJ:
> l2cap_data_channel_srejframe(chan, rx_control);
> break;
>
> - case L2CAP_SUPER_RCV_NOT_READY:
> + case L2CAP_SUPER_RNR:
> l2cap_data_channel_rnrframe(chan, rx_control);
> break;
> }
> @@ -3858,12 +3888,11 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont
> static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
> {
> struct l2cap_chan *chan = l2cap_pi(sk)->chan;
> - u16 control;
> - u8 req_seq;
> + u32 control;
> + u16 req_seq;
> int len, next_tx_seq_offset, req_seq_offset;
>
> - control = get_unaligned_le16(skb->data);
> - skb_pull(skb, 2);
> + control = __get_control_pull(chan, skb, skb->data);
> len = skb->len;
>
> /*
> @@ -3874,8 +3903,9 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
> if (l2cap_check_fcs(chan, skb))
> goto drop;
>
> - if (__is_sar_start(control) && __is_iframe(control))
> - len -= 2;
> + if (__is_sar_start(chan, control) &&
> + !__is_sframe(chan, control))
> + len -= L2CAP_SDULEN_SIZE;
>
> if (chan->fcs == L2CAP_FCS_CRC16)
> len -= 2;
> @@ -3885,7 +3915,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
> goto drop;
> }
>
> - req_seq = __get_reqseq(control);
> + req_seq = __get_reqseq(chan, control);
> req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
> if (req_seq_offset < 0)
> req_seq_offset += 64;
> @@ -3901,7 +3931,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
> goto drop;
> }
>
> - if (__is_iframe(control)) {
> + if (!__is_sframe(chan, control)) {
> if (len < 0) {
> l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
> goto drop;
> @@ -3929,8 +3959,8 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
> {
> struct l2cap_chan *chan;
> struct sock *sk = NULL;
> - u16 control;
> - u8 tx_seq;
> + u32 control;
> + u16 tx_seq;
> int len;
>
> chan = l2cap_get_chan_by_scid(conn, cid);
> @@ -3971,23 +4001,22 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
> goto done;
>
> case L2CAP_MODE_STREAMING:
> - control = get_unaligned_le16(skb->data);
> - skb_pull(skb, 2);
> + control = __get_control_pull(chan, skb, skb->data);
> len = skb->len;
>
> if (l2cap_check_fcs(chan, skb))
> goto drop;
>
> - if (__is_sar_start(control))
> - len -= 2;
> + if (__is_sar_start(chan, control))
> + len -= L2CAP_SDULEN_SIZE;
>
> if (chan->fcs == L2CAP_FCS_CRC16)
> len -= 2;
>
> - if (len > chan->mps || len < 0 || __is_sframe(control))
> + if (len > chan->mps || len < 0 || __is_sframe(chan, control))
> goto drop;
>
> - tx_seq = __get_txseq(control);
> + tx_seq = __get_txseq(chan, control);
>
> if (chan->expected_tx_seq != tx_seq) {
> /* Frame(s) missing - must discard partial SDU */
Otherwise looks pretty good.
Gustavo
next prev parent reply other threads:[~2011-09-14 2:48 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-07 14:05 [PATCHv1 0/5] EWS: extended window size and extended control field support Emeltchenko Andrei
2011-09-07 14:05 ` [PATCHv1 1/5] Bluetooth: EWS: extended window size option support Emeltchenko Andrei
2011-09-14 3:39 ` Gustavo Padovan
2011-09-07 14:05 ` [PATCHv1 2/5] Bluetooth: EWS: l2cap extended control field support Emeltchenko Andrei
2011-09-14 2:48 ` Gustavo Padovan [this message]
2011-09-07 14:05 ` [PATCHv1 3/5] Bluetooth: EWS: support extended seq numbers Emeltchenko Andrei
2011-09-14 3:43 ` Gustavo Padovan
2011-09-07 14:05 ` [PATCHv1 4/5] Bluetooth: EWS: remove magic numbers in l2cap Emeltchenko Andrei
2011-09-07 14:05 ` [PATCHv1 5/5] Bluetooth: EWS: prevent unneeded fragmentation " Emeltchenko Andrei
2011-09-14 3:51 ` Gustavo Padovan
2011-09-16 11:43 ` Emeltchenko Andrei
2011-09-19 17:13 ` Gustavo Padovan
2011-09-20 6:28 ` Emeltchenko Andrei
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110914024808.GK16856@joana \
--to=padovan@profusion.mobi \
--cc=Andrei.Emeltchenko.news@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).