aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/l2cap.c
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2010-05-01 15:15:36 -0400
committerMarcel Holtmann <marcel@holtmann.org>2010-05-10 03:28:46 -0400
commitd5392c8f1e9faef089bb7cb66c3314da8bddd1fe (patch)
tree4a935a46f0bfe2b9eb6d94f1d18fa079d2e1d095 /net/bluetooth/l2cap.c
parente8235c6bdd1c7ffbaa7eb8dcdbb46c51f1e5d72e (diff)
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>
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r--net/bluetooth/l2cap.c43
1 files changed, 39 insertions, 4 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index a9c152a09f0b..06687e264703 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1383,6 +1383,10 @@ static int l2cap_ertm_send(struct sock *sk)
1383 bt_cb(skb)->retries++; 1383 bt_cb(skb)->retries++;
1384 1384
1385 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); 1385 control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
1386 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
1387 control |= L2CAP_CTRL_FINAL;
1388 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
1389 }
1386 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) 1390 control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
1387 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); 1391 | (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
1388 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); 1392 put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
@@ -1404,6 +1408,7 @@ static int l2cap_ertm_send(struct sock *sk)
1404 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; 1408 pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
1405 1409
1406 pi->unacked_frames++; 1410 pi->unacked_frames++;
1411 pi->frames_sent++;
1407 1412
1408 if (skb_queue_is_last(TX_QUEUE(sk), skb)) 1413 if (skb_queue_is_last(TX_QUEUE(sk), skb))
1409 sk->sk_send_head = NULL; 1414 sk->sk_send_head = NULL;
@@ -2191,6 +2196,7 @@ static inline void l2cap_ertm_init(struct sock *sk)
2191 l2cap_pi(sk)->unacked_frames = 0; 2196 l2cap_pi(sk)->unacked_frames = 0;
2192 l2cap_pi(sk)->buffer_seq = 0; 2197 l2cap_pi(sk)->buffer_seq = 0;
2193 l2cap_pi(sk)->num_to_ack = 0; 2198 l2cap_pi(sk)->num_to_ack = 0;
2199 l2cap_pi(sk)->frames_sent = 0;
2194 2200
2195 setup_timer(&l2cap_pi(sk)->retrans_timer, 2201 setup_timer(&l2cap_pi(sk)->retrans_timer,
2196 l2cap_retrans_timeout, (unsigned long) sk); 2202 l2cap_retrans_timeout, (unsigned long) sk);
@@ -3148,6 +3154,38 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
3148 return 0; 3154 return 0;
3149} 3155}
3150 3156
3157static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
3158{
3159 struct l2cap_pinfo *pi = l2cap_pi(sk);
3160 u16 control = 0;
3161
3162 pi->frames_sent = 0;
3163 pi->conn_state |= L2CAP_CONN_SEND_FBIT;
3164
3165 control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3166
3167 if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
3168 control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL;
3169 l2cap_send_sframe(pi, control);
3170 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
3171 }
3172
3173 if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0)
3174 __mod_retrans_timer();
3175
3176 l2cap_ertm_send(sk);
3177
3178 if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
3179 pi->frames_sent == 0) {
3180 control |= L2CAP_SUPER_RCV_READY;
3181 if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
3182 control |= L2CAP_CTRL_FINAL;
3183 pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
3184 }
3185 l2cap_send_sframe(pi, control);
3186 }
3187}
3188
3151static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar) 3189static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
3152{ 3190{
3153 struct sk_buff *next_skb; 3191 struct sk_buff *next_skb;
@@ -3418,10 +3456,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
3418 switch (rx_control & L2CAP_CTRL_SUPERVISE) { 3456 switch (rx_control & L2CAP_CTRL_SUPERVISE) {
3419 case L2CAP_SUPER_RCV_READY: 3457 case L2CAP_SUPER_RCV_READY:
3420 if (rx_control & L2CAP_CTRL_POLL) { 3458 if (rx_control & L2CAP_CTRL_POLL) {
3421 u16 control = L2CAP_CTRL_FINAL; 3459 l2cap_send_i_or_rr_or_rnr(sk);
3422 control |= L2CAP_SUPER_RCV_READY |
3423 (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT);
3424 l2cap_send_sframe(l2cap_pi(sk), control);
3425 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; 3460 pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
3426 3461
3427 } else if (rx_control & L2CAP_CTRL_FINAL) { 3462 } else if (rx_control & L2CAP_CTRL_FINAL) {