Bluetooth: Initialize variables and timers for both channel's sides
authorGustavo F. Padovan <gustavo@las.ic.unicamp.br>
Sat, 3 Oct 2009 05:34:36 +0000 (02:34 -0300)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 3 Dec 2009 18:34:22 +0000 (19:34 +0100)
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>
net/bluetooth/l2cap.c

index 54992f7..dfd0327 100644 (file)
@@ -2173,6 +2173,21 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
        *ptr += L2CAP_CONF_OPT_SIZE + len;
 }
 
+static inline void l2cap_ertm_init(struct sock *sk)
+{
+       l2cap_pi(sk)->expected_ack_seq = 0;
+       l2cap_pi(sk)->unacked_frames = 0;
+       l2cap_pi(sk)->buffer_seq = 0;
+       l2cap_pi(sk)->num_to_ack = 0;
+
+       setup_timer(&l2cap_pi(sk)->retrans_timer,
+                       l2cap_retrans_timeout, (unsigned long) sk);
+       setup_timer(&l2cap_pi(sk)->monitor_timer,
+                       l2cap_monitor_timeout, (unsigned long) sk);
+
+       __skb_queue_head_init(SREJ_QUEUE(sk));
+}
+
 static int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
 {
        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
                        l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
 
                sk->sk_state = BT_CONNECTED;
-               l2cap_pi(sk)->next_tx_seq = 0;
-               l2cap_pi(sk)->expected_ack_seq = 0;
-               l2cap_pi(sk)->unacked_frames = 0;
-
-               setup_timer(&l2cap_pi(sk)->retrans_timer,
-                               l2cap_retrans_timeout, (unsigned long) sk);
-               setup_timer(&l2cap_pi(sk)->monitor_timer,
-                               l2cap_monitor_timeout, (unsigned long) sk);
 
+               l2cap_pi(sk)->next_tx_seq = 0;
+               l2cap_pi(sk)->expected_tx_seq = 0;
                __skb_queue_head_init(TX_QUEUE(sk));
-               __skb_queue_head_init(SREJ_QUEUE(sk));
+               if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
+                       l2cap_ertm_init(sk);
+
                l2cap_chan_ready(sk);
                goto unlock;
        }
@@ -2850,11 +2861,12 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                        l2cap_pi(sk)->fcs = L2CAP_FCS_CRC16;
 
                sk->sk_state = BT_CONNECTED;
+               l2cap_pi(sk)->next_tx_seq = 0;
                l2cap_pi(sk)->expected_tx_seq = 0;
-               l2cap_pi(sk)->buffer_seq = 0;
-               l2cap_pi(sk)->num_to_ack = 0;
                __skb_queue_head_init(TX_QUEUE(sk));
-               __skb_queue_head_init(SREJ_QUEUE(sk));
+               if (l2cap_pi(sk)->mode ==  L2CAP_MODE_ERTM)
+                       l2cap_ertm_init(sk);
+
                l2cap_chan_ready(sk);
        }
 
@@ -2886,9 +2898,12 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
        sk->sk_shutdown = SHUTDOWN_MASK;
 
        skb_queue_purge(TX_QUEUE(sk));
-       skb_queue_purge(SREJ_QUEUE(sk));
-       del_timer(&l2cap_pi(sk)->retrans_timer);
-       del_timer(&l2cap_pi(sk)->monitor_timer);
+
+       if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
+               skb_queue_purge(SREJ_QUEUE(sk));
+               del_timer(&l2cap_pi(sk)->retrans_timer);
+               del_timer(&l2cap_pi(sk)->monitor_timer);
+       }
 
        l2cap_chan_del(sk, ECONNRESET);
        bh_unlock_sock(sk);
@@ -2913,9 +2928,12 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
                return 0;
 
        skb_queue_purge(TX_QUEUE(sk));
-       skb_queue_purge(SREJ_QUEUE(sk));
-       del_timer(&l2cap_pi(sk)->retrans_timer);
-       del_timer(&l2cap_pi(sk)->monitor_timer);
+
+       if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
+               skb_queue_purge(SREJ_QUEUE(sk));
+               del_timer(&l2cap_pi(sk)->retrans_timer);
+               del_timer(&l2cap_pi(sk)->monitor_timer);
+       }
 
        l2cap_chan_del(sk, 0);
        bh_unlock_sock(sk);