aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/l2cap.c
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2010-07-08 19:08:18 -0400
committerMarcel Holtmann <marcel@holtmann.org>2010-07-21 13:39:11 -0400
commite9aeb2ddd441f0c8699ff04c499d7213730a0f04 (patch)
treeabce4d9b29979f7aef33378744322f0074f57b73 /net/bluetooth/l2cap.c
parent963cf687e825f7a59817f145a1ea19bdc224a18f (diff)
Bluetooth: Send ConfigReq after send a ConnectionRsp
The extended L2CAP features requires that one should initiate a ConfigReq after send the ConnectionRsp. This patch changes the behaviour of the configuration process of our stack. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r--net/bluetooth/l2cap.c44
1 files changed, 41 insertions, 3 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index a3dfee97ab9d..e366be0792cb 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -74,6 +74,7 @@ static void __l2cap_sock_close(struct sock *sk, int reason);
74static void l2cap_sock_close(struct sock *sk); 74static void l2cap_sock_close(struct sock *sk);
75static void l2cap_sock_kill(struct sock *sk); 75static void l2cap_sock_kill(struct sock *sk);
76 76
77static int l2cap_build_conf_req(struct sock *sk, void *data);
77static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, 78static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
78 u8 code, u8 ident, u16 dlen, void *data); 79 u8 code, u8 ident, u16 dlen, void *data);
79 80
@@ -548,6 +549,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
548 } 549 }
549 } else if (sk->sk_state == BT_CONNECT2) { 550 } else if (sk->sk_state == BT_CONNECT2) {
550 struct l2cap_conn_rsp rsp; 551 struct l2cap_conn_rsp rsp;
552 char buf[128];
551 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); 553 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
552 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); 554 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
553 555
@@ -570,6 +572,17 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
570 572
571 l2cap_send_cmd(conn, l2cap_pi(sk)->ident, 573 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
572 L2CAP_CONN_RSP, sizeof(rsp), &rsp); 574 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
575
576 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
577 rsp.result != L2CAP_CR_SUCCESS) {
578 bh_unlock_sock(sk);
579 continue;
580 }
581
582 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
583 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
584 l2cap_build_conf_req(sk, buf), buf);
585 l2cap_pi(sk)->num_conf_req++;
573 } 586 }
574 587
575 bh_unlock_sock(sk); 588 bh_unlock_sock(sk);
@@ -1897,6 +1910,8 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
1897 1910
1898 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { 1911 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
1899 struct l2cap_conn_rsp rsp; 1912 struct l2cap_conn_rsp rsp;
1913 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
1914 u8 buf[128];
1900 1915
1901 sk->sk_state = BT_CONFIG; 1916 sk->sk_state = BT_CONFIG;
1902 1917
@@ -1907,6 +1922,16 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
1907 l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident, 1922 l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
1908 L2CAP_CONN_RSP, sizeof(rsp), &rsp); 1923 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1909 1924
1925 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) {
1926 release_sock(sk);
1927 return 0;
1928 }
1929
1930 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
1931 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1932 l2cap_build_conf_req(sk, buf), buf);
1933 l2cap_pi(sk)->num_conf_req++;
1934
1910 release_sock(sk); 1935 release_sock(sk);
1911 return 0; 1936 return 0;
1912 } 1937 }
@@ -2613,7 +2638,7 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
2613 } 2638 }
2614 } 2639 }
2615 2640
2616 if (pi->num_conf_rsp || pi->num_conf_req) 2641 if (pi->num_conf_rsp || pi->num_conf_req > 1)
2617 goto done; 2642 goto done;
2618 2643
2619 switch (pi->mode) { 2644 switch (pi->mode) {
@@ -2857,7 +2882,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
2857 struct l2cap_chan_list *list = &conn->chan_list; 2882 struct l2cap_chan_list *list = &conn->chan_list;
2858 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; 2883 struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
2859 struct l2cap_conn_rsp rsp; 2884 struct l2cap_conn_rsp rsp;
2860 struct sock *sk, *parent; 2885 struct sock *parent, *uninitialized_var(sk);
2861 int result, status = L2CAP_CS_NO_INFO; 2886 int result, status = L2CAP_CS_NO_INFO;
2862 2887
2863 u16 dcid = 0, scid = __le16_to_cpu(req->scid); 2888 u16 dcid = 0, scid = __le16_to_cpu(req->scid);
@@ -2966,6 +2991,15 @@ sendresp:
2966 L2CAP_INFO_REQ, sizeof(info), &info); 2991 L2CAP_INFO_REQ, sizeof(info), &info);
2967 } 2992 }
2968 2993
2994 if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
2995 result == L2CAP_CR_SUCCESS) {
2996 u8 buf[128];
2997 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
2998 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2999 l2cap_build_conf_req(sk, buf), buf);
3000 l2cap_pi(sk)->num_conf_req++;
3001 }
3002
2969 return 0; 3003 return 0;
2970} 3004}
2971 3005
@@ -2998,9 +3032,13 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
2998 sk->sk_state = BT_CONFIG; 3032 sk->sk_state = BT_CONFIG;
2999 l2cap_pi(sk)->ident = 0; 3033 l2cap_pi(sk)->ident = 0;
3000 l2cap_pi(sk)->dcid = dcid; 3034 l2cap_pi(sk)->dcid = dcid;
3001 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
3002 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND; 3035 l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
3003 3036
3037 if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
3038 break;
3039
3040 l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
3041
3004 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, 3042 l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3005 l2cap_build_conf_req(sk, req), req); 3043 l2cap_build_conf_req(sk, req), req);
3006 l2cap_pi(sk)->num_conf_req++; 3044 l2cap_pi(sk)->num_conf_req++;