diff options
-rw-r--r-- | include/net/bluetooth/l2cap.h | 27 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 41 |
2 files changed, 45 insertions, 23 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index fa7edabde4d9..f24f5cf820d7 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -140,10 +140,10 @@ struct l2cap_conninfo { | |||
140 | #define L2CAP_EXT_CTRL_TXSEQ_SHIFT 18 | 140 | #define L2CAP_EXT_CTRL_TXSEQ_SHIFT 18 |
141 | 141 | ||
142 | /* L2CAP Supervisory Function */ | 142 | /* L2CAP Supervisory Function */ |
143 | #define L2CAP_SUPER_RCV_READY 0x0000 | 143 | #define L2CAP_SUPER_RR 0x00 |
144 | #define L2CAP_SUPER_REJECT 0x0004 | 144 | #define L2CAP_SUPER_REJ 0x01 |
145 | #define L2CAP_SUPER_RCV_NOT_READY 0x0008 | 145 | #define L2CAP_SUPER_RNR 0x02 |
146 | #define L2CAP_SUPER_SELECT_REJECT 0x000C | 146 | #define L2CAP_SUPER_SREJ 0x03 |
147 | 147 | ||
148 | /* L2CAP Segmentation and Reassembly */ | 148 | /* L2CAP Segmentation and Reassembly */ |
149 | #define L2CAP_SDU_UNSEGMENTED 0x0000 | 149 | #define L2CAP_SDU_UNSEGMENTED 0x0000 |
@@ -518,6 +518,25 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch) | |||
518 | #define __is_sframe(ctrl) ((ctrl) & L2CAP_CTRL_FRAME_TYPE) | 518 | #define __is_sframe(ctrl) ((ctrl) & L2CAP_CTRL_FRAME_TYPE) |
519 | #define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START) | 519 | #define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START) |
520 | 520 | ||
521 | static inline __u8 __get_ctrl_super(struct l2cap_chan *chan, __u32 ctrl) | ||
522 | { | ||
523 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
524 | return (ctrl & L2CAP_EXT_CTRL_SUPERVISE) >> | ||
525 | L2CAP_EXT_CTRL_SUPER_SHIFT; | ||
526 | else | ||
527 | return (ctrl & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; | ||
528 | } | ||
529 | |||
530 | static inline __u32 __set_ctrl_super(struct l2cap_chan *chan, __u32 super) | ||
531 | { | ||
532 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | ||
533 | return (super << L2CAP_EXT_CTRL_SUPER_SHIFT) & | ||
534 | L2CAP_EXT_CTRL_SUPERVISE; | ||
535 | else | ||
536 | return (super << L2CAP_CTRL_SUPER_SHIFT) & | ||
537 | L2CAP_CTRL_SUPERVISE; | ||
538 | } | ||
539 | |||
521 | extern int disable_ertm; | 540 | extern int disable_ertm; |
522 | 541 | ||
523 | int l2cap_init_sockets(void); | 542 | int l2cap_init_sockets(void); |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 6e343126f388..93b5da69cda5 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -613,10 +613,10 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control) | |||
613 | static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control) | 613 | static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control) |
614 | { | 614 | { |
615 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | 615 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { |
616 | control |= L2CAP_SUPER_RCV_NOT_READY; | 616 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); |
617 | set_bit(CONN_RNR_SENT, &chan->conn_state); | 617 | set_bit(CONN_RNR_SENT, &chan->conn_state); |
618 | } else | 618 | } else |
619 | control |= L2CAP_SUPER_RCV_READY; | 619 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); |
620 | 620 | ||
621 | control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | 621 | control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; |
622 | 622 | ||
@@ -1408,7 +1408,7 @@ static void l2cap_send_ack(struct l2cap_chan *chan) | |||
1408 | control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | 1408 | control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; |
1409 | 1409 | ||
1410 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | 1410 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { |
1411 | control |= L2CAP_SUPER_RCV_NOT_READY; | 1411 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); |
1412 | set_bit(CONN_RNR_SENT, &chan->conn_state); | 1412 | set_bit(CONN_RNR_SENT, &chan->conn_state); |
1413 | l2cap_send_sframe(chan, control); | 1413 | l2cap_send_sframe(chan, control); |
1414 | return; | 1414 | return; |
@@ -1417,7 +1417,7 @@ static void l2cap_send_ack(struct l2cap_chan *chan) | |||
1417 | if (l2cap_ertm_send(chan) > 0) | 1417 | if (l2cap_ertm_send(chan) > 0) |
1418 | return; | 1418 | return; |
1419 | 1419 | ||
1420 | control |= L2CAP_SUPER_RCV_READY; | 1420 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); |
1421 | l2cap_send_sframe(chan, control); | 1421 | l2cap_send_sframe(chan, control); |
1422 | } | 1422 | } |
1423 | 1423 | ||
@@ -1426,7 +1426,7 @@ static void l2cap_send_srejtail(struct l2cap_chan *chan) | |||
1426 | struct srej_list *tail; | 1426 | struct srej_list *tail; |
1427 | u16 control; | 1427 | u16 control; |
1428 | 1428 | ||
1429 | control = L2CAP_SUPER_SELECT_REJECT; | 1429 | control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); |
1430 | control |= L2CAP_CTRL_FINAL; | 1430 | control |= L2CAP_CTRL_FINAL; |
1431 | 1431 | ||
1432 | tail = list_entry((&chan->srej_l)->prev, struct srej_list, list); | 1432 | tail = list_entry((&chan->srej_l)->prev, struct srej_list, list); |
@@ -3119,7 +3119,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) | |||
3119 | control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | 3119 | control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; |
3120 | 3120 | ||
3121 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { | 3121 | if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { |
3122 | control |= L2CAP_SUPER_RCV_NOT_READY; | 3122 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); |
3123 | l2cap_send_sframe(chan, control); | 3123 | l2cap_send_sframe(chan, control); |
3124 | set_bit(CONN_RNR_SENT, &chan->conn_state); | 3124 | set_bit(CONN_RNR_SENT, &chan->conn_state); |
3125 | } | 3125 | } |
@@ -3131,7 +3131,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) | |||
3131 | 3131 | ||
3132 | if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && | 3132 | if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && |
3133 | chan->frames_sent == 0) { | 3133 | chan->frames_sent == 0) { |
3134 | control |= L2CAP_SUPER_RCV_READY; | 3134 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); |
3135 | l2cap_send_sframe(chan, control); | 3135 | l2cap_send_sframe(chan, control); |
3136 | } | 3136 | } |
3137 | } | 3137 | } |
@@ -3287,7 +3287,7 @@ static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan) | |||
3287 | set_bit(CONN_LOCAL_BUSY, &chan->conn_state); | 3287 | set_bit(CONN_LOCAL_BUSY, &chan->conn_state); |
3288 | 3288 | ||
3289 | control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | 3289 | control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; |
3290 | control |= L2CAP_SUPER_RCV_NOT_READY; | 3290 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); |
3291 | l2cap_send_sframe(chan, control); | 3291 | l2cap_send_sframe(chan, control); |
3292 | 3292 | ||
3293 | set_bit(CONN_RNR_SENT, &chan->conn_state); | 3293 | set_bit(CONN_RNR_SENT, &chan->conn_state); |
@@ -3303,7 +3303,8 @@ static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan) | |||
3303 | goto done; | 3303 | goto done; |
3304 | 3304 | ||
3305 | control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; | 3305 | control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; |
3306 | control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL; | 3306 | control |= L2CAP_CTRL_POLL; |
3307 | control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); | ||
3307 | l2cap_send_sframe(chan, control); | 3308 | l2cap_send_sframe(chan, control); |
3308 | chan->retry_count = 1; | 3309 | chan->retry_count = 1; |
3309 | 3310 | ||
@@ -3367,7 +3368,7 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq) | |||
3367 | kfree(l); | 3368 | kfree(l); |
3368 | return; | 3369 | return; |
3369 | } | 3370 | } |
3370 | control = L2CAP_SUPER_SELECT_REJECT; | 3371 | control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); |
3371 | control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; | 3372 | control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; |
3372 | l2cap_send_sframe(chan, control); | 3373 | l2cap_send_sframe(chan, control); |
3373 | list_del(&l->list); | 3374 | list_del(&l->list); |
@@ -3381,7 +3382,7 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq) | |||
3381 | u16 control; | 3382 | u16 control; |
3382 | 3383 | ||
3383 | while (tx_seq != chan->expected_tx_seq) { | 3384 | while (tx_seq != chan->expected_tx_seq) { |
3384 | control = L2CAP_SUPER_SELECT_REJECT; | 3385 | control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ); |
3385 | control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; | 3386 | control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; |
3386 | l2cap_send_sframe(chan, control); | 3387 | l2cap_send_sframe(chan, control); |
3387 | 3388 | ||
@@ -3645,10 +3646,12 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_c | |||
3645 | return; | 3646 | return; |
3646 | } | 3647 | } |
3647 | 3648 | ||
3648 | if (rx_control & L2CAP_CTRL_POLL) | 3649 | if (rx_control & L2CAP_CTRL_POLL) { |
3649 | l2cap_send_srejtail(chan); | 3650 | l2cap_send_srejtail(chan); |
3650 | else | 3651 | } else { |
3651 | l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY); | 3652 | rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR); |
3653 | l2cap_send_sframe(chan, rx_control); | ||
3654 | } | ||
3652 | } | 3655 | } |
3653 | 3656 | ||
3654 | static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) | 3657 | static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb) |
@@ -3663,20 +3666,20 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont | |||
3663 | clear_bit(CONN_WAIT_F, &chan->conn_state); | 3666 | clear_bit(CONN_WAIT_F, &chan->conn_state); |
3664 | } | 3667 | } |
3665 | 3668 | ||
3666 | switch (rx_control & L2CAP_CTRL_SUPERVISE) { | 3669 | switch (__get_ctrl_super(chan, rx_control)) { |
3667 | case L2CAP_SUPER_RCV_READY: | 3670 | case L2CAP_SUPER_RR: |
3668 | l2cap_data_channel_rrframe(chan, rx_control); | 3671 | l2cap_data_channel_rrframe(chan, rx_control); |
3669 | break; | 3672 | break; |
3670 | 3673 | ||
3671 | case L2CAP_SUPER_REJECT: | 3674 | case L2CAP_SUPER_REJ: |
3672 | l2cap_data_channel_rejframe(chan, rx_control); | 3675 | l2cap_data_channel_rejframe(chan, rx_control); |
3673 | break; | 3676 | break; |
3674 | 3677 | ||
3675 | case L2CAP_SUPER_SELECT_REJECT: | 3678 | case L2CAP_SUPER_SREJ: |
3676 | l2cap_data_channel_srejframe(chan, rx_control); | 3679 | l2cap_data_channel_srejframe(chan, rx_control); |
3677 | break; | 3680 | break; |
3678 | 3681 | ||
3679 | case L2CAP_SUPER_RCV_NOT_READY: | 3682 | case L2CAP_SUPER_RNR: |
3680 | l2cap_data_channel_rnrframe(chan, rx_control); | 3683 | l2cap_data_channel_rnrframe(chan, rx_control); |
3681 | break; | 3684 | break; |
3682 | } | 3685 | } |