mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-20 16:46:23 +08:00
Bluetooth: Implement 'Send IorRRorRNR' event
After receive a RR with P bit set ERTM shall use this funcion to choose what type of frame to reply with F bit = 1. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
e8235c6bdd
commit
d5392c8f1e
@ -320,7 +320,7 @@ struct l2cap_pinfo {
|
||||
__u8 conf_req[64];
|
||||
__u8 conf_len;
|
||||
__u8 conf_state;
|
||||
__u8 conn_state;
|
||||
__u16 conn_state;
|
||||
|
||||
__u8 next_tx_seq;
|
||||
__u8 expected_ack_seq;
|
||||
@ -328,6 +328,7 @@ struct l2cap_pinfo {
|
||||
__u8 buffer_seq;
|
||||
__u8 buffer_seq_srej;
|
||||
__u8 srej_save_reqseq;
|
||||
__u8 frames_sent;
|
||||
__u8 unacked_frames;
|
||||
__u8 retry_count;
|
||||
__u8 num_to_ack;
|
||||
@ -367,14 +368,15 @@ struct l2cap_pinfo {
|
||||
#define L2CAP_CONF_MAX_CONF_REQ 2
|
||||
#define L2CAP_CONF_MAX_CONF_RSP 2
|
||||
|
||||
#define L2CAP_CONN_SAR_SDU 0x01
|
||||
#define L2CAP_CONN_SREJ_SENT 0x02
|
||||
#define L2CAP_CONN_WAIT_F 0x04
|
||||
#define L2CAP_CONN_SREJ_ACT 0x08
|
||||
#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 L2CAP_CONN_SAR_SDU 0x0001
|
||||
#define L2CAP_CONN_SREJ_SENT 0x0002
|
||||
#define L2CAP_CONN_WAIT_F 0x0004
|
||||
#define L2CAP_CONN_SREJ_ACT 0x0008
|
||||
#define L2CAP_CONN_SEND_PBIT 0x0010
|
||||
#define L2CAP_CONN_REMOTE_BUSY 0x0020
|
||||
#define L2CAP_CONN_LOCAL_BUSY 0x0040
|
||||
#define L2CAP_CONN_REJ_ACT 0x0080
|
||||
#define L2CAP_CONN_SEND_FBIT 0x0100
|
||||
|
||||
#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \
|
||||
jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user