diff options
author | Andrei Emeltchenko <andrei.emeltchenko@intel.com> | 2012-09-27 10:26:20 -0400 |
---|---|---|
committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2012-09-27 16:31:18 -0400 |
commit | 93c284ee901f7d7bdd09087e92abefb7496c3777 (patch) | |
tree | 06da0dca5976737f6eef22387ebe91ca11356b6e /net | |
parent | a02226d6ff5098e6b97590cc55aabe7faf0860ed (diff) |
Bluetooth: AMP: Write remote AMP Assoc
When receiving HCI Command Status after HCI Create Physical Link
execute HCI Write Remote AMP Assoc command to AMP controller.
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/amp.c | 80 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 29 |
2 files changed, 109 insertions, 0 deletions
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c index 657ec736bbc6..5895ad0d2ac9 100644 --- a/net/bluetooth/amp.c +++ b/net/bluetooth/amp.c | |||
@@ -233,6 +233,86 @@ 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 | ||
236 | |||
237 | /* Write AMP Assoc data fragments, returns true with last fragment written*/ | ||
238 | static bool amp_write_rem_assoc_frag(struct hci_dev *hdev, | ||
239 | struct hci_conn *hcon) | ||
240 | { | ||
241 | struct hci_cp_write_remote_amp_assoc *cp; | ||
242 | struct amp_mgr *mgr = hcon->amp_mgr; | ||
243 | struct amp_ctrl *ctrl; | ||
244 | u16 frag_len, len; | ||
245 | |||
246 | ctrl = amp_ctrl_lookup(mgr, hcon->remote_id); | ||
247 | if (!ctrl) | ||
248 | return false; | ||
249 | |||
250 | if (!ctrl->assoc_rem_len) { | ||
251 | BT_DBG("all fragments are written"); | ||
252 | ctrl->assoc_rem_len = ctrl->assoc_len; | ||
253 | ctrl->assoc_len_so_far = 0; | ||
254 | |||
255 | amp_ctrl_put(ctrl); | ||
256 | return true; | ||
257 | } | ||
258 | |||
259 | frag_len = min_t(u16, 248, ctrl->assoc_rem_len); | ||
260 | len = frag_len + sizeof(*cp); | ||
261 | |||
262 | cp = kzalloc(len, GFP_KERNEL); | ||
263 | if (!cp) { | ||
264 | amp_ctrl_put(ctrl); | ||
265 | return false; | ||
266 | } | ||
267 | |||
268 | BT_DBG("hcon %p ctrl %p frag_len %u assoc_len %u rem_len %u", | ||
269 | hcon, ctrl, frag_len, ctrl->assoc_len, ctrl->assoc_rem_len); | ||
270 | |||
271 | cp->phy_handle = hcon->handle; | ||
272 | cp->len_so_far = cpu_to_le16(ctrl->assoc_len_so_far); | ||
273 | cp->rem_len = cpu_to_le16(ctrl->assoc_rem_len); | ||
274 | memcpy(cp->frag, ctrl->assoc, frag_len); | ||
275 | |||
276 | ctrl->assoc_len_so_far += frag_len; | ||
277 | ctrl->assoc_rem_len -= frag_len; | ||
278 | |||
279 | amp_ctrl_put(ctrl); | ||
280 | |||
281 | hci_send_cmd(hdev, HCI_OP_WRITE_REMOTE_AMP_ASSOC, len, cp); | ||
282 | |||
283 | kfree(cp); | ||
284 | |||
285 | return false; | ||
286 | } | ||
287 | |||
288 | void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle) | ||
289 | { | ||
290 | struct hci_conn *hcon; | ||
291 | |||
292 | BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle); | ||
293 | |||
294 | hcon = hci_conn_hash_lookup_handle(hdev, handle); | ||
295 | if (!hcon) | ||
296 | return; | ||
297 | |||
298 | amp_write_rem_assoc_frag(hdev, hcon); | ||
299 | } | ||
300 | |||
301 | void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle) | ||
302 | { | ||
303 | struct hci_conn *hcon; | ||
304 | |||
305 | BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle); | ||
306 | |||
307 | hcon = hci_conn_hash_lookup_handle(hdev, handle); | ||
308 | if (!hcon) | ||
309 | return; | ||
310 | |||
311 | BT_DBG("%s phy handle 0x%2.2x hcon %p", hdev->name, handle, hcon); | ||
312 | |||
313 | amp_write_rem_assoc_frag(hdev, hcon); | ||
314 | } | ||
315 | |||
236 | void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | 316 | void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, |
237 | struct hci_conn *hcon) | 317 | struct hci_conn *hcon) |
238 | { | 318 | { |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index bd06ef95693d..0b7ba1e39d45 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -1215,6 +1215,20 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, | |||
1215 | hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); | 1215 | hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); |
1216 | } | 1216 | } |
1217 | 1217 | ||
1218 | static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, | ||
1219 | struct sk_buff *skb) | ||
1220 | { | ||
1221 | struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; | ||
1222 | |||
1223 | BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", | ||
1224 | hdev->name, rp->status, rp->phy_handle); | ||
1225 | |||
1226 | if (rp->status) | ||
1227 | return; | ||
1228 | |||
1229 | amp_write_rem_assoc_continue(hdev, rp->phy_handle); | ||
1230 | } | ||
1231 | |||
1218 | static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | 1232 | static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) |
1219 | { | 1233 | { |
1220 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1234 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
@@ -1700,7 +1714,18 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) | |||
1700 | 1714 | ||
1701 | static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) | 1715 | static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) |
1702 | { | 1716 | { |
1717 | struct hci_cp_create_phy_link *cp; | ||
1718 | |||
1703 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1719 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1720 | |||
1721 | if (status) | ||
1722 | return; | ||
1723 | |||
1724 | cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); | ||
1725 | if (!cp) | ||
1726 | return; | ||
1727 | |||
1728 | amp_write_remote_assoc(hdev, cp->phy_handle); | ||
1704 | } | 1729 | } |
1705 | 1730 | ||
1706 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1731 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -2436,6 +2461,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2436 | hci_cc_write_le_host_supported(hdev, skb); | 2461 | hci_cc_write_le_host_supported(hdev, skb); |
2437 | break; | 2462 | break; |
2438 | 2463 | ||
2464 | case HCI_OP_WRITE_REMOTE_AMP_ASSOC: | ||
2465 | hci_cc_write_remote_amp_assoc(hdev, skb); | ||
2466 | break; | ||
2467 | |||
2439 | default: | 2468 | default: |
2440 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); | 2469 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); |
2441 | break; | 2470 | break; |