aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAndrei Emeltchenko <andrei.emeltchenko@intel.com>2012-09-27 10:26:20 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-09-27 16:31:18 -0400
commit93c284ee901f7d7bdd09087e92abefb7496c3777 (patch)
tree06da0dca5976737f6eef22387ebe91ca11356b6e /net
parenta02226d6ff5098e6b97590cc55aabe7faf0860ed (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.c80
-rw-r--r--net/bluetooth/hci_event.c29
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*/
238static 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
288void 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
301void 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
236void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, 316void 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
1218static 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
1218static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1232static 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
1701static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) 1715static 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
1706static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1731static 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;