diff options
-rw-r--r-- | include/net/bluetooth/l2cap.h | 20 | ||||
-rw-r--r-- | net/bluetooth/l2cap.c | 43 |
2 files changed, 50 insertions, 13 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 17a689f27a6a..d9c20c3d6f3d 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -320,7 +320,7 @@ struct l2cap_pinfo { | |||
320 | __u8 conf_req[64]; | 320 | __u8 conf_req[64]; |
321 | __u8 conf_len; | 321 | __u8 conf_len; |
322 | __u8 conf_state; | 322 | __u8 conf_state; |
323 | __u8 conn_state; | 323 | __u16 conn_state; |
324 | 324 | ||
325 | __u8 next_tx_seq; | 325 | __u8 next_tx_seq; |
326 | __u8 expected_ack_seq; | 326 | __u8 expected_ack_seq; |
@@ -328,6 +328,7 @@ struct l2cap_pinfo { | |||
328 | __u8 buffer_seq; | 328 | __u8 buffer_seq; |
329 | __u8 buffer_seq_srej; | 329 | __u8 buffer_seq_srej; |
330 | __u8 srej_save_reqseq; | 330 | __u8 srej_save_reqseq; |
331 | __u8 frames_sent; | ||
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; |
@@ -367,14 +368,15 @@ struct l2cap_pinfo { | |||
367 | #define L2CAP_CONF_MAX_CONF_REQ 2 | 368 | #define L2CAP_CONF_MAX_CONF_REQ 2 |
368 | #define L2CAP_CONF_MAX_CONF_RSP 2 | 369 | #define L2CAP_CONF_MAX_CONF_RSP 2 |
369 | 370 | ||
370 | #define L2CAP_CONN_SAR_SDU 0x01 | 371 | #define L2CAP_CONN_SAR_SDU 0x0001 |
371 | #define L2CAP_CONN_SREJ_SENT 0x02 | 372 | #define L2CAP_CONN_SREJ_SENT 0x0002 |
372 | #define L2CAP_CONN_WAIT_F 0x04 | 373 | #define L2CAP_CONN_WAIT_F 0x0004 |
373 | #define L2CAP_CONN_SREJ_ACT 0x08 | 374 | #define L2CAP_CONN_SREJ_ACT 0x0008 |
374 | #define L2CAP_CONN_SEND_PBIT 0x10 | 375 | #define L2CAP_CONN_SEND_PBIT 0x0010 |
375 | #define L2CAP_CONN_REMOTE_BUSY 0x20 | 376 | #define L2CAP_CONN_REMOTE_BUSY 0x0020 |
376 | #define L2CAP_CONN_LOCAL_BUSY 0x40 | 377 | #define L2CAP_CONN_LOCAL_BUSY 0x0040 |
377 | #define L2CAP_CONN_REJ_ACT 0x80 | 378 | #define L2CAP_CONN_REJ_ACT 0x0080 |
379 | #define L2CAP_CONN_SEND_FBIT 0x0100 | ||
378 | 380 | ||
379 | #define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ | 381 | #define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ |
380 | jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); | 382 | jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); |
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 | ||
3157 | static 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 | |||
3151 | static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar) | 3189 | static 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) { |