aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo F. Padovan <gustavo@las.ic.unicamp.br>2009-08-20 21:26:04 -0400
committerMarcel Holtmann <marcel@holtmann.org>2009-08-22 18:03:43 -0400
commitef54fd937fbd5ebaeb023818524565bd526a5f36 (patch)
treec664288f00548b8c531ff44a0bc8c7f18542740e
parent8f17154f1f70fcc6faa31ac82164fcf7f0599f38 (diff)
Bluetooth: Full support for receiving L2CAP SREJ frames
Support for receiving of SREJ frames as specified by the state table. Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/l2cap.h3
-rw-r--r--net/bluetooth/l2cap.c30
2 files changed, 32 insertions, 1 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 9f2126a4f6f5..7ca614ac5d43 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -328,6 +328,7 @@ struct l2cap_pinfo {
328 __u8 expected_tx_seq; 328 __u8 expected_tx_seq;
329 __u8 buffer_seq; 329 __u8 buffer_seq;
330 __u8 buffer_seq_srej; 330 __u8 buffer_seq_srej;
331 __u8 srej_save_reqseq;
331 __u8 unacked_frames; 332 __u8 unacked_frames;
332 __u8 retry_count; 333 __u8 retry_count;
333 __u8 num_to_ack; 334 __u8 num_to_ack;
@@ -370,6 +371,8 @@ struct l2cap_pinfo {
370#define L2CAP_CONN_SAR_SDU 0x01 371#define L2CAP_CONN_SAR_SDU 0x01
371#define L2CAP_CONN_SREJ_SENT 0x02 372#define L2CAP_CONN_SREJ_SENT 0x02
372#define L2CAP_CONN_WAIT_F 0x04 373#define L2CAP_CONN_WAIT_F 0x04
374#define L2CAP_CONN_SREJ_ACT 0x08
375#define L2CAP_CONN_SEND_PBIT 0x10
373 376
374#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ 377#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \
375 jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); 378 jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 70aff921db8c..c04526f3df2e 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3241,6 +3241,10 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
3241 while (tx_seq != pi->expected_tx_seq) { 3241 while (tx_seq != pi->expected_tx_seq) {
3242 control = L2CAP_SUPER_SELECT_REJECT; 3242 control = L2CAP_SUPER_SELECT_REJECT;
3243 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; 3243 control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
3244 if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
3245 control |= L2CAP_CTRL_POLL;
3246 pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
3247 }
3244 l2cap_send_sframe(pi, control); 3248 l2cap_send_sframe(pi, control);
3245 3249
3246 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); 3250 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
@@ -3300,6 +3304,8 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
3300 __skb_queue_head_init(SREJ_QUEUE(sk)); 3304 __skb_queue_head_init(SREJ_QUEUE(sk));
3301 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); 3305 l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
3302 3306
3307 pi->conn_state |= L2CAP_CONN_SEND_PBIT;
3308
3303 l2cap_send_srejframe(sk, tx_seq); 3309 l2cap_send_srejframe(sk, tx_seq);
3304 } 3310 }
3305 return 0; 3311 return 0;
@@ -3370,7 +3376,29 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
3370 break; 3376 break;
3371 3377
3372 case L2CAP_SUPER_SELECT_REJECT: 3378 case L2CAP_SUPER_SELECT_REJECT:
3373 l2cap_retransmit_frame(sk, tx_seq); 3379 if (rx_control & L2CAP_CTRL_POLL) {
3380 l2cap_retransmit_frame(sk, tx_seq);
3381 pi->expected_ack_seq = tx_seq;
3382 l2cap_drop_acked_frames(sk);
3383 l2cap_ertm_send(sk);
3384 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3385 pi->srej_save_reqseq = tx_seq;
3386 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3387 }
3388 } else if (rx_control & L2CAP_CTRL_FINAL) {
3389 if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
3390 pi->srej_save_reqseq == tx_seq)
3391 pi->srej_save_reqseq &= ~L2CAP_CONN_SREJ_ACT;
3392 else
3393 l2cap_retransmit_frame(sk, tx_seq);
3394 }
3395 else {
3396 l2cap_retransmit_frame(sk, tx_seq);
3397 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3398 pi->srej_save_reqseq = tx_seq;
3399 pi->conn_state |= L2CAP_CONN_SREJ_ACT;
3400 }
3401 }
3374 break; 3402 break;
3375 3403
3376 case L2CAP_SUPER_RCV_NOT_READY: 3404 case L2CAP_SUPER_RCV_NOT_READY: