aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorGustavo F. Padovan <gustavo@las.ic.unicamp.br>2009-10-03 01:34:36 -0400
committerMarcel Holtmann <marcel@holtmann.org>2009-12-03 13:34:22 -0500
commit0565c1c24af94130b891f989fa608faddfadc52c (patch)
tree223bb84f663f3d2b21c57b264085abcf83c0f4a1 /net/bluetooth
parentcde9f807f003676862178a6f28b52c7d431511ed (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>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/l2cap.c54
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
2176static 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
2176static int l2cap_mode_supported(__u8 mode, __u32 feat_mask) 2191static 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);