aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/a2mp.h2
-rw-r--r--include/net/bluetooth/l2cap.h1
-rw-r--r--net/bluetooth/a2mp.c34
-rw-r--r--net/bluetooth/l2cap_core.c33
4 files changed, 60 insertions, 10 deletions
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 99c7389b9189..9fda7c94913f 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -28,6 +28,7 @@ struct amp_mgr {
28 struct list_head list; 28 struct list_head list;
29 struct l2cap_conn *l2cap_conn; 29 struct l2cap_conn *l2cap_conn;
30 struct l2cap_chan *a2mp_chan; 30 struct l2cap_chan *a2mp_chan;
31 struct l2cap_chan *bredr_chan;
31 struct kref kref; 32 struct kref kref;
32 __u8 ident; 33 __u8 ident;
33 __u8 handle; 34 __u8 handle;
@@ -137,6 +138,7 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
137 struct sk_buff *skb); 138 struct sk_buff *skb);
138struct amp_mgr *amp_mgr_lookup_by_state(u8 state); 139struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
139void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data); 140void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
141void a2mp_discover_amp(struct l2cap_chan *chan);
140void a2mp_send_getinfo_rsp(struct hci_dev *hdev); 142void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
141void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status); 143void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
142 144
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7ed8e356425a..aba830fc762f 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -767,6 +767,7 @@ int l2cap_chan_check_security(struct l2cap_chan *chan);
767void l2cap_chan_set_defaults(struct l2cap_chan *chan); 767void l2cap_chan_set_defaults(struct l2cap_chan *chan);
768int l2cap_ertm_init(struct l2cap_chan *chan); 768int l2cap_ertm_init(struct l2cap_chan *chan);
769void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); 769void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
770void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
770void l2cap_chan_del(struct l2cap_chan *chan, int err); 771void l2cap_chan_del(struct l2cap_chan *chan, int err);
771 772
772#endif /* __L2CAP_H */ 773#endif /* __L2CAP_H */
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index d0fde05e8b17..93adaad782ed 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -638,7 +638,7 @@ static struct l2cap_ops a2mp_chan_ops = {
638 .ready = l2cap_chan_no_ready, 638 .ready = l2cap_chan_no_ready,
639}; 639};
640 640
641static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn) 641static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
642{ 642{
643 struct l2cap_chan *chan; 643 struct l2cap_chan *chan;
644 int err; 644 int err;
@@ -673,7 +673,10 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn)
673 673
674 chan->conf_state = 0; 674 chan->conf_state = 0;
675 675
676 l2cap_chan_add(conn, chan); 676 if (locked)
677 __l2cap_chan_add(conn, chan);
678 else
679 l2cap_chan_add(conn, chan);
677 680
678 chan->remote_mps = chan->omtu; 681 chan->remote_mps = chan->omtu;
679 chan->mps = chan->omtu; 682 chan->mps = chan->omtu;
@@ -712,7 +715,7 @@ int amp_mgr_put(struct amp_mgr *mgr)
712 return kref_put(&mgr->kref, &amp_mgr_destroy); 715 return kref_put(&mgr->kref, &amp_mgr_destroy);
713} 716}
714 717
715static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn) 718static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn, bool locked)
716{ 719{
717 struct amp_mgr *mgr; 720 struct amp_mgr *mgr;
718 struct l2cap_chan *chan; 721 struct l2cap_chan *chan;
@@ -725,7 +728,7 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn)
725 728
726 mgr->l2cap_conn = conn; 729 mgr->l2cap_conn = conn;
727 730
728 chan = a2mp_chan_open(conn); 731 chan = a2mp_chan_open(conn, locked);
729 if (!chan) { 732 if (!chan) {
730 kfree(mgr); 733 kfree(mgr);
731 return NULL; 734 return NULL;
@@ -754,7 +757,7 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
754{ 757{
755 struct amp_mgr *mgr; 758 struct amp_mgr *mgr;
756 759
757 mgr = amp_mgr_create(conn); 760 mgr = amp_mgr_create(conn, false);
758 if (!mgr) { 761 if (!mgr) {
759 BT_ERR("Could not create AMP manager"); 762 BT_ERR("Could not create AMP manager");
760 return NULL; 763 return NULL;
@@ -842,3 +845,24 @@ void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
842 amp_mgr_put(mgr); 845 amp_mgr_put(mgr);
843 kfree(rsp); 846 kfree(rsp);
844} 847}
848
849void a2mp_discover_amp(struct l2cap_chan *chan)
850{
851 struct l2cap_conn *conn = chan->conn;
852 struct amp_mgr *mgr = conn->hcon->amp_mgr;
853 struct a2mp_discov_req req;
854
855 BT_DBG("chan %p conn %p mgr %p", chan, conn, mgr);
856
857 if (!mgr) {
858 mgr = amp_mgr_create(conn, true);
859 if (!mgr)
860 return;
861 }
862
863 mgr->bredr_chan = chan;
864
865 req.mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
866 req.ext_feat = 0;
867 a2mp_send(mgr, A2MP_DISCOVER_REQ, 1, sizeof(req), &req);
868}
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7a59e929febc..781a085ae5bc 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -455,7 +455,7 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
455 set_bit(FLAG_FORCE_ACTIVE, &chan->flags); 455 set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
456} 456}
457 457
458static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) 458void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
459{ 459{
460 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, 460 BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
461 __le16_to_cpu(chan->psm), chan->dcid); 461 __le16_to_cpu(chan->psm), chan->dcid);
@@ -946,6 +946,18 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
946 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 946 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
947} 947}
948 948
949static bool __amp_capable(struct l2cap_chan *chan)
950{
951 struct l2cap_conn *conn = chan->conn;
952
953 if (enable_hs &&
954 chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED &&
955 conn->fixed_chan_mask & L2CAP_FC_A2MP)
956 return true;
957 else
958 return false;
959}
960
949static void l2cap_send_conn_req(struct l2cap_chan *chan) 961static void l2cap_send_conn_req(struct l2cap_chan *chan)
950{ 962{
951 struct l2cap_conn *conn = chan->conn; 963 struct l2cap_conn *conn = chan->conn;
@@ -972,6 +984,16 @@ static void l2cap_chan_ready(struct l2cap_chan *chan)
972 chan->ops->ready(chan); 984 chan->ops->ready(chan);
973} 985}
974 986
987static void l2cap_start_connection(struct l2cap_chan *chan)
988{
989 if (__amp_capable(chan)) {
990 BT_DBG("chan %p AMP capable: discover AMPs", chan);
991 a2mp_discover_amp(chan);
992 } else {
993 l2cap_send_conn_req(chan);
994 }
995}
996
975static void l2cap_do_start(struct l2cap_chan *chan) 997static void l2cap_do_start(struct l2cap_chan *chan)
976{ 998{
977 struct l2cap_conn *conn = chan->conn; 999 struct l2cap_conn *conn = chan->conn;
@@ -986,8 +1008,9 @@ static void l2cap_do_start(struct l2cap_chan *chan)
986 return; 1008 return;
987 1009
988 if (l2cap_chan_check_security(chan) && 1010 if (l2cap_chan_check_security(chan) &&
989 __l2cap_no_conn_pending(chan)) 1011 __l2cap_no_conn_pending(chan)) {
990 l2cap_send_conn_req(chan); 1012 l2cap_start_connection(chan);
1013 }
991 } else { 1014 } else {
992 struct l2cap_info_req req; 1015 struct l2cap_info_req req;
993 req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); 1016 req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
@@ -1082,7 +1105,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
1082 continue; 1105 continue;
1083 } 1106 }
1084 1107
1085 l2cap_send_conn_req(chan); 1108 l2cap_start_connection(chan);
1086 1109
1087 } else if (chan->state == BT_CONNECT2) { 1110 } else if (chan->state == BT_CONNECT2) {
1088 struct l2cap_conn_rsp rsp; 1111 struct l2cap_conn_rsp rsp;
@@ -5456,7 +5479,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
5456 5479
5457 if (chan->state == BT_CONNECT) { 5480 if (chan->state == BT_CONNECT) {
5458 if (!status) { 5481 if (!status) {
5459 l2cap_send_conn_req(chan); 5482 l2cap_start_connection(chan);
5460 } else { 5483 } else {
5461 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); 5484 __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
5462 } 5485 }