|
@@ -1383,6 +1383,10 @@ static int l2cap_ertm_send(struct sock *sk)
|
|
|
bt_cb(skb)->retries++;
|
|
|
|
|
|
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
|
|
|
+ if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
|
|
|
+ control |= L2CAP_CTRL_FINAL;
|
|
|
+ pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
|
|
|
+ }
|
|
|
control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
|
|
|
| (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
|
|
|
put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
|
|
@@ -1404,6 +1408,7 @@ static int l2cap_ertm_send(struct sock *sk)
|
|
|
pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
|
|
|
|
|
|
pi->unacked_frames++;
|
|
|
+ pi->frames_sent++;
|
|
|
|
|
|
if (skb_queue_is_last(TX_QUEUE(sk), skb))
|
|
|
sk->sk_send_head = NULL;
|
|
@@ -2191,6 +2196,7 @@ static inline void l2cap_ertm_init(struct sock *sk)
|
|
|
l2cap_pi(sk)->unacked_frames = 0;
|
|
|
l2cap_pi(sk)->buffer_seq = 0;
|
|
|
l2cap_pi(sk)->num_to_ack = 0;
|
|
|
+ l2cap_pi(sk)->frames_sent = 0;
|
|
|
|
|
|
setup_timer(&l2cap_pi(sk)->retrans_timer,
|
|
|
l2cap_retrans_timeout, (unsigned long) sk);
|
|
@@ -3148,6 +3154,38 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
|
|
|
+{
|
|
|
+ struct l2cap_pinfo *pi = l2cap_pi(sk);
|
|
|
+ u16 control = 0;
|
|
|
+
|
|
|
+ pi->frames_sent = 0;
|
|
|
+ pi->conn_state |= L2CAP_CONN_SEND_FBIT;
|
|
|
+
|
|
|
+ control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
|
|
|
+
|
|
|
+ if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
|
|
|
+ control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL;
|
|
|
+ l2cap_send_sframe(pi, control);
|
|
|
+ pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0)
|
|
|
+ __mod_retrans_timer();
|
|
|
+
|
|
|
+ l2cap_ertm_send(sk);
|
|
|
+
|
|
|
+ if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
|
|
|
+ pi->frames_sent == 0) {
|
|
|
+ control |= L2CAP_SUPER_RCV_READY;
|
|
|
+ if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
|
|
|
+ control |= L2CAP_CTRL_FINAL;
|
|
|
+ pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
|
|
|
+ }
|
|
|
+ l2cap_send_sframe(pi, control);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
|
|
|
{
|
|
|
struct sk_buff *next_skb;
|
|
@@ -3418,10 +3456,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
|
|
|
switch (rx_control & L2CAP_CTRL_SUPERVISE) {
|
|
|
case L2CAP_SUPER_RCV_READY:
|
|
|
if (rx_control & L2CAP_CTRL_POLL) {
|
|
|
- u16 control = L2CAP_CTRL_FINAL;
|
|
|
- control |= L2CAP_SUPER_RCV_READY |
|
|
|
- (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT);
|
|
|
- l2cap_send_sframe(l2cap_pi(sk), control);
|
|
|
+ l2cap_send_i_or_rr_or_rnr(sk);
|
|
|
pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
|
|
|
|
|
|
} else if (rx_control & L2CAP_CTRL_FINAL) {
|