Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ec10d97 authored by Gustavo Padovan's avatar Gustavo Padovan Committed by Marcel Holtmann
Browse files

Bluetooth: Implement RejActioned flag



RejActioned is used to prevent retransmission when a entity is on the
WAIT_F state, i.e., waiting for a frame with F-bit set due local busy
condition or a expired retransmission timer. (When these two events raise
they send a frame with the Poll bit set and enters in the WAIT_F state to
wait for a frame with the Final bit set.)
The local entity doesn't send I-frames(the data frames) until the receipt
of a frame with F-bit set. When that happens it also set RejActioned to false.
RejActioned is a mandatory feature of ERTM spec.

Signed-off-by: default avatarGustavo F. Padovan <gustavo@las.ic.unicamp.br>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 9f121a5a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -374,6 +374,7 @@ struct l2cap_pinfo {
#define L2CAP_CONN_SEND_PBIT       0x10
#define L2CAP_CONN_REMOTE_BUSY     0x20
#define L2CAP_CONN_LOCAL_BUSY      0x40
#define L2CAP_CONN_REJ_ACT         0x80

#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \
		jiffies +  msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
+35 −3
Original line number Diff line number Diff line
@@ -3362,6 +3362,16 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
		return 0;
	}

	if (rx_control & L2CAP_CTRL_FINAL) {
		if (pi->conn_state & L2CAP_CONN_REJ_ACT)
			pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
		else {
			sk->sk_send_head = TX_QUEUE(sk)->next;
			pi->next_tx_seq = pi->expected_ack_seq;
			l2cap_ertm_send(sk);
		}
	}

	pi->buffer_seq = (pi->buffer_seq + 1) % 64;

	err = l2cap_sar_reassembly_sdu(sk, skb, rx_control);
@@ -3398,6 +3408,14 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
			pi->expected_ack_seq = tx_seq;
			l2cap_drop_acked_frames(sk);

			if (pi->conn_state & L2CAP_CONN_REJ_ACT)
				pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
			else {
				sk->sk_send_head = TX_QUEUE(sk)->next;
				pi->next_tx_seq = pi->expected_ack_seq;
				l2cap_ertm_send(sk);
			}

			if (!(pi->conn_state & L2CAP_CONN_WAIT_F))
				break;

@@ -3425,11 +3443,25 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
		pi->expected_ack_seq = __get_reqseq(rx_control);
		l2cap_drop_acked_frames(sk);

		if (rx_control & L2CAP_CTRL_FINAL) {
			if (pi->conn_state & L2CAP_CONN_REJ_ACT)
				pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
			else {
				sk->sk_send_head = TX_QUEUE(sk)->next;
				pi->next_tx_seq = pi->expected_ack_seq;
				l2cap_ertm_send(sk);
			}
		} else {
			sk->sk_send_head = TX_QUEUE(sk)->next;
			pi->next_tx_seq = pi->expected_ack_seq;

			l2cap_ertm_send(sk);

			if (pi->conn_state & L2CAP_CONN_WAIT_F) {
				pi->srej_save_reqseq = tx_seq;
				pi->conn_state |= L2CAP_CONN_REJ_ACT;
			}
		}

		break;

	case L2CAP_SUPER_SELECT_REJECT: