diff options
author | Gustavo F. Padovan <gustavo@las.ic.unicamp.br> | 2009-10-03 01:34:36 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2009-12-03 13:34:22 -0500 |
commit | 0565c1c24af94130b891f989fa608faddfadc52c (patch) | |
tree | 223bb84f663f3d2b21c57b264085abcf83c0f4a1 | |
parent | cde9f807f003676862178a6f28b52c7d431511ed (diff) |
Bluetooth: Initialize variables and timers for both channel's sides
Fix ERTM's full-duplex channel to work as specified by ERTM spec. ERTM
needs to handle state vars, timers and counters to send and receive
I-frames(the data frames), i.e., for both sides of data communication.
We initialize all of them to the default values here.
Full-duplex channel is a mandatory feature of ERTM spec.
Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r-- | net/bluetooth/l2cap.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 54992f782301..dfd0327cf8da 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -2173,6 +2173,21 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) | |||
2173 | *ptr += L2CAP_CONF_OPT_SIZE + len; | 2173 | *ptr += L2CAP_CONF_OPT_SIZE + len; |
2174 | } | 2174 | } |
2175 | 2175 | ||
2176 | static inline void l2cap_ertm_init(struct sock *sk) | ||
2177 | { | ||
2178 | l2cap_pi(sk)->expected_ack_seq = 0; | ||
2179 | l2cap_pi(sk)->unacked_frames = 0; | ||
2180 | l2cap_pi(sk)->buffer_seq = 0; | ||
2181 | l2cap_pi(sk)->num_to_ack = 0; | ||
2182 | |||
2183 | setup_timer(&l2cap_pi(sk)->retrans_timer, | ||
2184 | l2cap_retrans_timeout, (unsigned long) sk); | ||
2185 | setup_timer(&l2cap_pi(sk)->monitor_timer, | ||
2186 | l2cap_monitor_timeout, (unsigned long) sk); | ||
2187 | |||
2188 | __skb_queue_head_init(SREJ_QUEUE(sk)); | ||
2189 | } | ||
2190 | |||
2176 | static int l2cap_mode_supported(__u8 mode, __u32 feat_mask) | 2191 | static int l2cap_mode_supported(__u8 mode, __u32 feat_mask) |
2177 | { | 2192 | { |
2178 | u32 local_feat_mask = l2cap_feat_mask; | 2193 | u32 local_feat_mask = l2cap_feat_mask; |
@@ -2761,17 +2776,13 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2761 | l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16; | 2776 | l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16; |
2762 | 2777 | ||
2763 | sk->sk_state = BT_CONNECTED; | 2778 | sk->sk_state = BT_CONNECTED; |
2764 | l2cap_pi(sk)->next_tx_seq = 0; | ||
2765 | l2cap_pi(sk)->expected_ack_seq = 0; | ||
2766 | l2cap_pi(sk)->unacked_frames = 0; | ||
2767 | |||
2768 | setup_timer(&l2cap_pi(sk)->retrans_timer, | ||
2769 | l2cap_retrans_timeout, (unsigned long) sk); | ||
2770 | setup_timer(&l2cap_pi(sk)->monitor_timer, | ||
2771 | l2cap_monitor_timeout, (unsigned long) sk); | ||
2772 | 2779 | ||
2780 | l2cap_pi(sk)->next_tx_seq = 0; | ||
2781 | l2cap_pi(sk)->expected_tx_seq = 0; | ||
2773 | __skb_queue_head_init(TX_QUEUE(sk)); | 2782 | __skb_queue_head_init(TX_QUEUE(sk)); |
2774 | __skb_queue_head_init(SREJ_QUEUE(sk)); | 2783 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) |
2784 | l2cap_ertm_init(sk); | ||
2785 | |||
2775 | l2cap_chan_ready(sk); | 2786 | l2cap_chan_ready(sk); |
2776 | goto unlock; | 2787 | goto unlock; |
2777 | } | 2788 | } |
@@ -2850,11 +2861,12 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2850 | l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16; | 2861 | l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16; |
2851 | 2862 | ||
2852 | sk->sk_state = BT_CONNECTED; | 2863 | sk->sk_state = BT_CONNECTED; |
2864 | l2cap_pi(sk)->next_tx_seq = 0; | ||
2853 | l2cap_pi(sk)->expected_tx_seq = 0; | 2865 | l2cap_pi(sk)->expected_tx_seq = 0; |
2854 | l2cap_pi(sk)->buffer_seq = 0; | ||
2855 | l2cap_pi(sk)->num_to_ack = 0; | ||
2856 | __skb_queue_head_init(TX_QUEUE(sk)); | 2866 | __skb_queue_head_init(TX_QUEUE(sk)); |
2857 | __skb_queue_head_init(SREJ_QUEUE(sk)); | 2867 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) |
2868 | l2cap_ertm_init(sk); | ||
2869 | |||
2858 | l2cap_chan_ready(sk); | 2870 | l2cap_chan_ready(sk); |
2859 | } | 2871 | } |
2860 | 2872 | ||
@@ -2886,9 +2898,12 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
2886 | sk->sk_shutdown = SHUTDOWN_MASK; | 2898 | sk->sk_shutdown = SHUTDOWN_MASK; |
2887 | 2899 | ||
2888 | skb_queue_purge(TX_QUEUE(sk)); | 2900 | skb_queue_purge(TX_QUEUE(sk)); |
2889 | skb_queue_purge(SREJ_QUEUE(sk)); | 2901 | |
2890 | del_timer(&l2cap_pi(sk)->retrans_timer); | 2902 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { |
2891 | del_timer(&l2cap_pi(sk)->monitor_timer); | 2903 | skb_queue_purge(SREJ_QUEUE(sk)); |
2904 | del_timer(&l2cap_pi(sk)->retrans_timer); | ||
2905 | del_timer(&l2cap_pi(sk)->monitor_timer); | ||
2906 | } | ||
2892 | 2907 | ||
2893 | l2cap_chan_del(sk, ECONNRESET); | 2908 | l2cap_chan_del(sk, ECONNRESET); |
2894 | bh_unlock_sock(sk); | 2909 | bh_unlock_sock(sk); |
@@ -2913,9 +2928,12 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
2913 | return 0; | 2928 | return 0; |
2914 | 2929 | ||
2915 | skb_queue_purge(TX_QUEUE(sk)); | 2930 | skb_queue_purge(TX_QUEUE(sk)); |
2916 | skb_queue_purge(SREJ_QUEUE(sk)); | 2931 | |
2917 | del_timer(&l2cap_pi(sk)->retrans_timer); | 2932 | if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { |
2918 | del_timer(&l2cap_pi(sk)->monitor_timer); | 2933 | skb_queue_purge(SREJ_QUEUE(sk)); |
2934 | del_timer(&l2cap_pi(sk)->retrans_timer); | ||
2935 | del_timer(&l2cap_pi(sk)->monitor_timer); | ||
2936 | } | ||
2919 | 2937 | ||
2920 | l2cap_chan_del(sk, 0); | 2938 | l2cap_chan_del(sk, 0); |
2921 | bh_unlock_sock(sk); | 2939 | bh_unlock_sock(sk); |