aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/l2cap_core.c
diff options
context:
space:
mode:
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>2011-10-17 05:19:57 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-10-17 16:04:00 -0400
commit836be934218eb80abc5515d584c329c26951086f (patch)
treeb8ee564f2ae0dc2f34fd9b0b7c2f9fb08fa917f1 /net/bluetooth/l2cap_core.c
parent88843ab06b6f279bff1c32e4218541ac7efe2600 (diff)
Bluetooth: EWS: support extended seq numbers
Adds support for extended sequence numbers found in extended control fields. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/l2cap_core.c')
-rw-r--r--net/bluetooth/l2cap_core.c63
1 files changed, 30 insertions, 33 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index a25394231b48..86c8720043ea 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1295,7 +1295,7 @@ static void l2cap_streaming_send(struct l2cap_chan *chan)
1295 1295
1296 l2cap_do_send(chan, skb); 1296 l2cap_do_send(chan, skb);
1297 1297
1298 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64; 1298 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
1299 } 1299 }
1300} 1300}
1301 1301
@@ -1389,7 +1389,8 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
1389 __set_retrans_timer(chan); 1389 __set_retrans_timer(chan);
1390 1390
1391 bt_cb(skb)->tx_seq = chan->next_tx_seq; 1391 bt_cb(skb)->tx_seq = chan->next_tx_seq;
1392 chan->next_tx_seq = (chan->next_tx_seq + 1) % 64; 1392
1393 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
1393 1394
1394 if (bt_cb(skb)->retries == 1) 1395 if (bt_cb(skb)->retries == 1)
1395 chan->unacked_frames++; 1396 chan->unacked_frames++;
@@ -1967,12 +1968,15 @@ static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
1967static inline void l2cap_txwin_setup(struct l2cap_chan *chan) 1968static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
1968{ 1969{
1969 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && 1970 if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
1970 __l2cap_ews_supported(chan)) 1971 __l2cap_ews_supported(chan)) {
1971 /* use extended control field */ 1972 /* use extended control field */
1972 set_bit(FLAG_EXT_CTRL, &chan->flags); 1973 set_bit(FLAG_EXT_CTRL, &chan->flags);
1973 else 1974 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
1975 } else {
1974 chan->tx_win = min_t(u16, chan->tx_win, 1976 chan->tx_win = min_t(u16, chan->tx_win,
1975 L2CAP_DEFAULT_TX_WINDOW); 1977 L2CAP_DEFAULT_TX_WINDOW);
1978 chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
1979 }
1976} 1980}
1977 1981
1978static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) 1982static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
@@ -2138,6 +2142,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
2138 2142
2139 set_bit(FLAG_EXT_CTRL, &chan->flags); 2143 set_bit(FLAG_EXT_CTRL, &chan->flags);
2140 set_bit(CONF_EWS_RECV, &chan->conf_state); 2144 set_bit(CONF_EWS_RECV, &chan->conf_state);
2145 chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2141 chan->remote_tx_win = val; 2146 chan->remote_tx_win = val;
2142 break; 2147 break;
2143 2148
@@ -3225,18 +3230,14 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb,
3225 return 0; 3230 return 0;
3226 } 3231 }
3227 3232
3228 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64; 3233 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
3229 if (tx_seq_offset < 0)
3230 tx_seq_offset += 64;
3231 3234
3232 do { 3235 do {
3233 if (bt_cb(next_skb)->tx_seq == tx_seq) 3236 if (bt_cb(next_skb)->tx_seq == tx_seq)
3234 return -EINVAL; 3237 return -EINVAL;
3235 3238
3236 next_tx_seq_offset = (bt_cb(next_skb)->tx_seq - 3239 next_tx_seq_offset = __seq_offset(chan,
3237 chan->buffer_seq) % 64; 3240 bt_cb(next_skb)->tx_seq, chan->buffer_seq);
3238 if (next_tx_seq_offset < 0)
3239 next_tx_seq_offset += 64;
3240 3241
3241 if (next_tx_seq_offset > tx_seq_offset) { 3242 if (next_tx_seq_offset > tx_seq_offset) {
3242 __skb_queue_before(&chan->srej_q, next_skb, skb); 3243 __skb_queue_before(&chan->srej_q, next_skb, skb);
@@ -3426,9 +3427,8 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
3426 break; 3427 break;
3427 } 3428 }
3428 3429
3429 chan->buffer_seq_srej = 3430 chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3430 (chan->buffer_seq_srej + 1) % 64; 3431 tx_seq = __next_seq(chan, tx_seq);
3431 tx_seq = (tx_seq + 1) % 64;
3432 } 3432 }
3433} 3433}
3434 3434
@@ -3463,10 +3463,13 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
3463 3463
3464 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); 3464 new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
3465 new->tx_seq = chan->expected_tx_seq; 3465 new->tx_seq = chan->expected_tx_seq;
3466 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; 3466
3467 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3468
3467 list_add_tail(&new->list, &chan->srej_l); 3469 list_add_tail(&new->list, &chan->srej_l);
3468 } 3470 }
3469 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; 3471
3472 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3470} 3473}
3471 3474
3472static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) 3475static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
@@ -3492,9 +3495,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
3492 chan->expected_ack_seq = req_seq; 3495 chan->expected_ack_seq = req_seq;
3493 l2cap_drop_acked_frames(chan); 3496 l2cap_drop_acked_frames(chan);
3494 3497
3495 tx_seq_offset = (tx_seq - chan->buffer_seq) % 64; 3498 tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
3496 if (tx_seq_offset < 0)
3497 tx_seq_offset += 64;
3498 3499
3499 /* invalid tx_seq */ 3500 /* invalid tx_seq */
3500 if (tx_seq_offset >= chan->tx_win) { 3501 if (tx_seq_offset >= chan->tx_win) {
@@ -3542,10 +3543,8 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
3542 l2cap_send_srejframe(chan, tx_seq); 3543 l2cap_send_srejframe(chan, tx_seq);
3543 } 3544 }
3544 } else { 3545 } else {
3545 expected_tx_seq_offset = 3546 expected_tx_seq_offset = __seq_offset(chan,
3546 (chan->expected_tx_seq - chan->buffer_seq) % 64; 3547 chan->expected_tx_seq, chan->buffer_seq);
3547 if (expected_tx_seq_offset < 0)
3548 expected_tx_seq_offset += 64;
3549 3548
3550 /* duplicated tx_seq */ 3549 /* duplicated tx_seq */
3551 if (tx_seq_offset < expected_tx_seq_offset) 3550 if (tx_seq_offset < expected_tx_seq_offset)
@@ -3570,7 +3569,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
3570 return 0; 3569 return 0;
3571 3570
3572expected: 3571expected:
3573 chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; 3572 chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3574 3573
3575 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) { 3574 if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
3576 bt_cb(skb)->tx_seq = tx_seq; 3575 bt_cb(skb)->tx_seq = tx_seq;
@@ -3580,7 +3579,8 @@ expected:
3580 } 3579 }
3581 3580
3582 err = l2cap_reassemble_sdu(chan, skb, rx_control); 3581 err = l2cap_reassemble_sdu(chan, skb, rx_control);
3583 chan->buffer_seq = (chan->buffer_seq + 1) % 64; 3582 chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
3583
3584 if (err < 0) { 3584 if (err < 0) {
3585 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 3585 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3586 return err; 3586 return err;
@@ -3794,14 +3794,11 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
3794 } 3794 }
3795 3795
3796 req_seq = __get_reqseq(chan, control); 3796 req_seq = __get_reqseq(chan, control);
3797 req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
3798 if (req_seq_offset < 0)
3799 req_seq_offset += 64;
3800 3797
3801 next_tx_seq_offset = 3798 req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
3802 (chan->next_tx_seq - chan->expected_ack_seq) % 64; 3799
3803 if (next_tx_seq_offset < 0) 3800 next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
3804 next_tx_seq_offset += 64; 3801 chan->expected_ack_seq);
3805 3802
3806 /* check for invalid req-seq */ 3803 /* check for invalid req-seq */
3807 if (req_seq_offset > next_tx_seq_offset) { 3804 if (req_seq_offset > next_tx_seq_offset) {
@@ -3907,7 +3904,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
3907 /* TODO: Notify userland of missing data */ 3904 /* TODO: Notify userland of missing data */
3908 } 3905 }
3909 3906
3910 chan->expected_tx_seq = (tx_seq + 1) % 64; 3907 chan->expected_tx_seq = __next_seq(chan, tx_seq);
3911 3908
3912 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE) 3909 if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
3913 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); 3910 l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);