aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/a2mp.h3
-rw-r--r--include/net/bluetooth/amp.h2
-rw-r--r--include/net/bluetooth/l2cap.h2
-rw-r--r--net/bluetooth/a2mp.c41
-rw-r--r--net/bluetooth/amp.c15
-rw-r--r--net/bluetooth/hci_event.c21
6 files changed, 83 insertions, 1 deletions
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 9fda7c94913f..e776ab2dc572 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -22,6 +22,7 @@
22enum amp_mgr_state { 22enum amp_mgr_state {
23 READ_LOC_AMP_INFO, 23 READ_LOC_AMP_INFO,
24 READ_LOC_AMP_ASSOC, 24 READ_LOC_AMP_ASSOC,
25 READ_LOC_AMP_ASSOC_FINAL,
25}; 26};
26 27
27struct amp_mgr { 28struct amp_mgr {
@@ -134,6 +135,7 @@ extern struct mutex amp_mgr_list_lock;
134 135
135void amp_mgr_get(struct amp_mgr *mgr); 136void amp_mgr_get(struct amp_mgr *mgr);
136int amp_mgr_put(struct amp_mgr *mgr); 137int amp_mgr_put(struct amp_mgr *mgr);
138u8 __next_ident(struct amp_mgr *mgr);
137struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, 139struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
138 struct sk_buff *skb); 140 struct sk_buff *skb);
139struct amp_mgr *amp_mgr_lookup_by_state(u8 state); 141struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
@@ -141,5 +143,6 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
141void a2mp_discover_amp(struct l2cap_chan *chan); 143void a2mp_discover_amp(struct l2cap_chan *chan);
142void a2mp_send_getinfo_rsp(struct hci_dev *hdev); 144void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
143void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status); 145void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
146void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status);
144 147
145#endif /* __A2MP_H */ 148#endif /* __A2MP_H */
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index 8f8032965eaf..70496c07afaa 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -37,6 +37,8 @@ int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);
37void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr); 37void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
38void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle); 38void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
39void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr); 39void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
40void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
41 struct hci_conn *hcon);
40void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, 42void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
41 struct hci_conn *hcon); 43 struct hci_conn *hcon);
42void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle); 44void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 0967f9e33750..ab58b81fb7c5 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -508,6 +508,8 @@ struct l2cap_chan {
508 __u32 remote_acc_lat; 508 __u32 remote_acc_lat;
509 __u32 remote_flush_to; 509 __u32 remote_flush_to;
510 510
511 __u8 ctrl_id;
512
511 struct delayed_work chan_timer; 513 struct delayed_work chan_timer;
512 struct delayed_work retrans_timer; 514 struct delayed_work retrans_timer;
513 struct delayed_work monitor_timer; 515 struct delayed_work monitor_timer;
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 28d1246958be..375a67f501d0 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -67,7 +67,7 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
67 kfree(cmd); 67 kfree(cmd);
68} 68}
69 69
70static u8 __next_ident(struct amp_mgr *mgr) 70u8 __next_ident(struct amp_mgr *mgr)
71{ 71{
72 if (++mgr->ident == 0) 72 if (++mgr->ident == 0)
73 mgr->ident = 1; 73 mgr->ident = 1;
@@ -420,6 +420,8 @@ static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
420 420
421 BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id); 421 BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id);
422 422
423 mgr->bredr_chan->ctrl_id = rsp->id;
424
423 amp_create_phylink(hdev, mgr, hcon); 425 amp_create_phylink(hdev, mgr, hcon);
424 426
425done: 427done:
@@ -876,6 +878,43 @@ void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
876 kfree(rsp); 878 kfree(rsp);
877} 879}
878 880
881void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status)
882{
883 struct amp_mgr *mgr;
884 struct amp_assoc *loc_assoc = &hdev->loc_assoc;
885 struct a2mp_physlink_req *req;
886 struct l2cap_chan *bredr_chan;
887 size_t len;
888
889 mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC_FINAL);
890 if (!mgr)
891 return;
892
893 len = sizeof(*req) + loc_assoc->len;
894
895 BT_DBG("%s mgr %p assoc_len %zu", hdev->name, mgr, len);
896
897 req = kzalloc(len, GFP_KERNEL);
898 if (!req) {
899 amp_mgr_put(mgr);
900 return;
901 }
902
903 bredr_chan = mgr->bredr_chan;
904 if (!bredr_chan)
905 goto clean;
906
907 req->local_id = hdev->id;
908 req->remote_id = bredr_chan->ctrl_id;
909 memcpy(req->amp_assoc, loc_assoc->data, loc_assoc->len);
910
911 a2mp_send(mgr, A2MP_CREATEPHYSLINK_REQ, __next_ident(mgr), len, req);
912
913clean:
914 amp_mgr_put(mgr);
915 kfree(req);
916}
917
879void a2mp_discover_amp(struct l2cap_chan *chan) 918void a2mp_discover_amp(struct l2cap_chan *chan)
880{ 919{
881 struct l2cap_conn *conn = chan->conn; 920 struct l2cap_conn *conn = chan->conn;
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index 5895ad0d2ac9..4f7b2647d5e9 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -233,6 +233,21 @@ void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
233 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); 233 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
234} 234}
235 235
236void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
237 struct hci_conn *hcon)
238{
239 struct hci_cp_read_local_amp_assoc cp;
240 struct amp_mgr *mgr = hcon->amp_mgr;
241
242 cp.phy_handle = hcon->handle;
243 cp.len_so_far = cpu_to_le16(0);
244 cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
245
246 mgr->state = READ_LOC_AMP_ASSOC_FINAL;
247
248 /* Read Local AMP Assoc final link information data */
249 hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
250}
236 251
237/* Write AMP Assoc data fragments, returns true with last fragment written*/ 252/* Write AMP Assoc data fragments, returns true with last fragment written*/
238static bool amp_write_rem_assoc_frag(struct hci_dev *hdev, 253static bool amp_write_rem_assoc_frag(struct hci_dev *hdev,
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0b7ba1e39d45..d702ba1c171c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -901,6 +901,7 @@ static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev,
901a2mp_rsp: 901a2mp_rsp:
902 /* Send A2MP Rsp when all fragments are received */ 902 /* Send A2MP Rsp when all fragments are received */
903 a2mp_send_getampassoc_rsp(hdev, rp->status); 903 a2mp_send_getampassoc_rsp(hdev, rp->status);
904 a2mp_send_create_phy_link_req(hdev, rp->status);
904} 905}
905 906
906static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 907static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
@@ -3641,6 +3642,22 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
3641 } 3642 }
3642} 3643}
3643 3644
3645static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
3646{
3647 struct hci_ev_channel_selected *ev = (void *) skb->data;
3648 struct hci_conn *hcon;
3649
3650 BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
3651
3652 skb_pull(skb, sizeof(*ev));
3653
3654 hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
3655 if (!hcon)
3656 return;
3657
3658 amp_read_loc_assoc_final_data(hdev, hcon);
3659}
3660
3644void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 3661void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3645{ 3662{
3646 struct hci_event_hdr *hdr = (void *) skb->data; 3663 struct hci_event_hdr *hdr = (void *) skb->data;
@@ -3805,6 +3822,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
3805 hci_le_meta_evt(hdev, skb); 3822 hci_le_meta_evt(hdev, skb);
3806 break; 3823 break;
3807 3824
3825 case HCI_EV_CHANNEL_SELECTED:
3826 hci_chan_selected_evt(hdev, skb);
3827 break;
3828
3808 case HCI_EV_REMOTE_OOB_DATA_REQUEST: 3829 case HCI_EV_REMOTE_OOB_DATA_REQUEST:
3809 hci_remote_oob_data_request_evt(hdev, skb); 3830 hci_remote_oob_data_request_evt(hdev, skb);
3810 break; 3831 break;