aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>2012-09-27 10:26:22 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-09-27 16:34:06 -0400
commit9495b2ee757f7747d7c28f9ba8d7edc53005ec2d (patch)
tree196d6c79f2c5836fc55c5515d9ece5e3d6aab254 /net
parent2766be48a7181d7f2a84831ca7e7be248fb6fdb5 (diff)
Bluetooth: AMP: Process Chan Selected event
Channel Selected event indicates that link information data is available. Read it with Read Local AMP Assoc command. The data shall be sent in the A2MP Create Physical Link Request. Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/a2mp.c41
-rw-r--r--net/bluetooth/amp.c15
-rw-r--r--net/bluetooth/hci_event.c21
3 files changed, 76 insertions, 1 deletions
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;