diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-01-30 14:21:04 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-01-30 14:21:04 -0500 |
commit | 0f496df2d9ba48faa808b5fa330de0da1a2d29d7 (patch) | |
tree | c1c85a625cff3f2ca6d95a5d5020a0157baa7521 /net/bluetooth | |
parent | 56e1bd770614da94f35e88c150cf9edf8d0b57a2 (diff) | |
parent | 9b008c0457e583e10e62d1215bed6ab26ee54906 (diff) |
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/a2mp.c | 42 | ||||
-rw-r--r-- | net/bluetooth/amp.c | 25 | ||||
-rw-r--r-- | net/bluetooth/bnep/core.c | 1 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 20 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 60 | ||||
-rw-r--r-- | net/bluetooth/hci_sysfs.c | 22 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 5 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 270 |
8 files changed, 327 insertions, 118 deletions
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 2f67d5ecc907..eb0f4b16ff09 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -290,7 +290,7 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
290 | goto done; | 290 | goto done; |
291 | } | 291 | } |
292 | 292 | ||
293 | mgr->state = READ_LOC_AMP_INFO; | 293 | set_bit(READ_LOC_AMP_INFO, &mgr->state); |
294 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); | 294 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); |
295 | 295 | ||
296 | done: | 296 | done: |
@@ -499,8 +499,16 @@ send_rsp: | |||
499 | if (hdev) | 499 | if (hdev) |
500 | hci_dev_put(hdev); | 500 | hci_dev_put(hdev); |
501 | 501 | ||
502 | a2mp_send(mgr, A2MP_CREATEPHYSLINK_RSP, hdr->ident, sizeof(rsp), | 502 | /* Reply error now and success after HCI Write Remote AMP Assoc |
503 | &rsp); | 503 | command complete with success status |
504 | */ | ||
505 | if (rsp.status != A2MP_STATUS_SUCCESS) { | ||
506 | a2mp_send(mgr, A2MP_CREATEPHYSLINK_RSP, hdr->ident, | ||
507 | sizeof(rsp), &rsp); | ||
508 | } else { | ||
509 | set_bit(WRITE_REMOTE_AMP_ASSOC, &mgr->state); | ||
510 | mgr->ident = hdr->ident; | ||
511 | } | ||
504 | 512 | ||
505 | skb_pull(skb, le16_to_cpu(hdr->len)); | 513 | skb_pull(skb, le16_to_cpu(hdr->len)); |
506 | return 0; | 514 | return 0; |
@@ -840,7 +848,7 @@ struct amp_mgr *amp_mgr_lookup_by_state(u8 state) | |||
840 | 848 | ||
841 | mutex_lock(&_mgr_list_lock); | 849 | mutex_lock(&_mgr_list_lock); |
842 | list_for_each_entry(mgr, &_mgr_list, list) { | 850 | list_for_each_entry(mgr, &_mgr_list, list) { |
843 | if (mgr->state == state) { | 851 | if (test_and_clear_bit(state, &mgr->state)) { |
844 | amp_mgr_get(mgr); | 852 | amp_mgr_get(mgr); |
845 | mutex_unlock(&_mgr_list_lock); | 853 | mutex_unlock(&_mgr_list_lock); |
846 | return mgr; | 854 | return mgr; |
@@ -949,6 +957,32 @@ clean: | |||
949 | kfree(req); | 957 | kfree(req); |
950 | } | 958 | } |
951 | 959 | ||
960 | void a2mp_send_create_phy_link_rsp(struct hci_dev *hdev, u8 status) | ||
961 | { | ||
962 | struct amp_mgr *mgr; | ||
963 | struct a2mp_physlink_rsp rsp; | ||
964 | struct hci_conn *hs_hcon; | ||
965 | |||
966 | mgr = amp_mgr_lookup_by_state(WRITE_REMOTE_AMP_ASSOC); | ||
967 | if (!mgr) | ||
968 | return; | ||
969 | |||
970 | hs_hcon = hci_conn_hash_lookup_state(hdev, AMP_LINK, BT_CONNECT); | ||
971 | if (!hs_hcon) { | ||
972 | rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION; | ||
973 | } else { | ||
974 | rsp.remote_id = hs_hcon->remote_id; | ||
975 | rsp.status = A2MP_STATUS_SUCCESS; | ||
976 | } | ||
977 | |||
978 | BT_DBG("%s mgr %p hs_hcon %p status %u", hdev->name, mgr, hs_hcon, | ||
979 | status); | ||
980 | |||
981 | rsp.local_id = hdev->id; | ||
982 | a2mp_send(mgr, A2MP_CREATEPHYSLINK_RSP, mgr->ident, sizeof(rsp), &rsp); | ||
983 | amp_mgr_put(mgr); | ||
984 | } | ||
985 | |||
952 | void a2mp_discover_amp(struct l2cap_chan *chan) | 986 | void a2mp_discover_amp(struct l2cap_chan *chan) |
953 | { | 987 | { |
954 | struct l2cap_conn *conn = chan->conn; | 988 | struct l2cap_conn *conn = chan->conn; |
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c index 1b0d92c0643a..d459ed43c779 100644 --- a/net/bluetooth/amp.c +++ b/net/bluetooth/amp.c | |||
@@ -236,7 +236,7 @@ void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr) | |||
236 | 236 | ||
237 | cp.max_len = cpu_to_le16(hdev->amp_assoc_size); | 237 | cp.max_len = cpu_to_le16(hdev->amp_assoc_size); |
238 | 238 | ||
239 | mgr->state = READ_LOC_AMP_ASSOC; | 239 | set_bit(READ_LOC_AMP_ASSOC, &mgr->state); |
240 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | 240 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); |
241 | } | 241 | } |
242 | 242 | ||
@@ -250,7 +250,7 @@ void amp_read_loc_assoc_final_data(struct hci_dev *hdev, | |||
250 | cp.len_so_far = cpu_to_le16(0); | 250 | cp.len_so_far = cpu_to_le16(0); |
251 | cp.max_len = cpu_to_le16(hdev->amp_assoc_size); | 251 | cp.max_len = cpu_to_le16(hdev->amp_assoc_size); |
252 | 252 | ||
253 | mgr->state = READ_LOC_AMP_ASSOC_FINAL; | 253 | set_bit(READ_LOC_AMP_ASSOC_FINAL, &mgr->state); |
254 | 254 | ||
255 | /* Read Local AMP Assoc final link information data */ | 255 | /* Read Local AMP Assoc final link information data */ |
256 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | 256 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); |
@@ -317,7 +317,9 @@ void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle) | |||
317 | if (!hcon) | 317 | if (!hcon) |
318 | return; | 318 | return; |
319 | 319 | ||
320 | amp_write_rem_assoc_frag(hdev, hcon); | 320 | /* Send A2MP create phylink rsp when all fragments are written */ |
321 | if (amp_write_rem_assoc_frag(hdev, hcon)) | ||
322 | a2mp_send_create_phy_link_rsp(hdev, 0); | ||
321 | } | 323 | } |
322 | 324 | ||
323 | void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle) | 325 | void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle) |
@@ -403,26 +405,20 @@ void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon) | |||
403 | 405 | ||
404 | void amp_create_logical_link(struct l2cap_chan *chan) | 406 | void amp_create_logical_link(struct l2cap_chan *chan) |
405 | { | 407 | { |
408 | struct hci_conn *hs_hcon = chan->hs_hcon; | ||
406 | struct hci_cp_create_accept_logical_link cp; | 409 | struct hci_cp_create_accept_logical_link cp; |
407 | struct hci_conn *hcon; | ||
408 | struct hci_dev *hdev; | 410 | struct hci_dev *hdev; |
409 | 411 | ||
410 | BT_DBG("chan %p", chan); | 412 | BT_DBG("chan %p hs_hcon %p dst %pMR", chan, hs_hcon, chan->conn->dst); |
411 | 413 | ||
412 | if (!chan->hs_hcon) | 414 | if (!hs_hcon) |
413 | return; | 415 | return; |
414 | 416 | ||
415 | hdev = hci_dev_hold(chan->hs_hcon->hdev); | 417 | hdev = hci_dev_hold(chan->hs_hcon->hdev); |
416 | if (!hdev) | 418 | if (!hdev) |
417 | return; | 419 | return; |
418 | 420 | ||
419 | BT_DBG("chan %p dst %pMR", chan, chan->conn->dst); | 421 | cp.phy_handle = hs_hcon->handle; |
420 | |||
421 | hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, chan->conn->dst); | ||
422 | if (!hcon) | ||
423 | goto done; | ||
424 | |||
425 | cp.phy_handle = hcon->handle; | ||
426 | 422 | ||
427 | cp.tx_flow_spec.id = chan->local_id; | 423 | cp.tx_flow_spec.id = chan->local_id; |
428 | cp.tx_flow_spec.stype = chan->local_stype; | 424 | cp.tx_flow_spec.stype = chan->local_stype; |
@@ -438,14 +434,13 @@ void amp_create_logical_link(struct l2cap_chan *chan) | |||
438 | cp.rx_flow_spec.acc_lat = cpu_to_le32(chan->remote_acc_lat); | 434 | cp.rx_flow_spec.acc_lat = cpu_to_le32(chan->remote_acc_lat); |
439 | cp.rx_flow_spec.flush_to = cpu_to_le32(chan->remote_flush_to); | 435 | cp.rx_flow_spec.flush_to = cpu_to_le32(chan->remote_flush_to); |
440 | 436 | ||
441 | if (hcon->out) | 437 | if (hs_hcon->out) |
442 | hci_send_cmd(hdev, HCI_OP_CREATE_LOGICAL_LINK, sizeof(cp), | 438 | hci_send_cmd(hdev, HCI_OP_CREATE_LOGICAL_LINK, sizeof(cp), |
443 | &cp); | 439 | &cp); |
444 | else | 440 | else |
445 | hci_send_cmd(hdev, HCI_OP_ACCEPT_LOGICAL_LINK, sizeof(cp), | 441 | hci_send_cmd(hdev, HCI_OP_ACCEPT_LOGICAL_LINK, sizeof(cp), |
446 | &cp); | 442 | &cp); |
447 | 443 | ||
448 | done: | ||
449 | hci_dev_put(hdev); | 444 | hci_dev_put(hdev); |
450 | } | 445 | } |
451 | 446 | ||
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index a5b639702637..e430b1abcd2f 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -33,7 +33,6 @@ | |||
33 | 33 | ||
34 | #include <net/bluetooth/bluetooth.h> | 34 | #include <net/bluetooth/bluetooth.h> |
35 | #include <net/bluetooth/hci_core.h> | 35 | #include <net/bluetooth/hci_core.h> |
36 | #include <net/bluetooth/l2cap.h> | ||
37 | 36 | ||
38 | #include "bnep.h" | 37 | #include "bnep.h" |
39 | 38 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 0f78e34220c9..d13ce99b410a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -1146,7 +1146,8 @@ static void hci_power_on(struct work_struct *work) | |||
1146 | return; | 1146 | return; |
1147 | 1147 | ||
1148 | if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) | 1148 | if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) |
1149 | schedule_delayed_work(&hdev->power_off, HCI_AUTO_OFF_TIMEOUT); | 1149 | queue_delayed_work(hdev->req_workqueue, &hdev->power_off, |
1150 | HCI_AUTO_OFF_TIMEOUT); | ||
1150 | 1151 | ||
1151 | if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags)) | 1152 | if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags)) |
1152 | mgmt_index_added(hdev); | 1153 | mgmt_index_added(hdev); |
@@ -1621,8 +1622,8 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval, | |||
1621 | if (err < 0) | 1622 | if (err < 0) |
1622 | return err; | 1623 | return err; |
1623 | 1624 | ||
1624 | schedule_delayed_work(&hdev->le_scan_disable, | 1625 | queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, |
1625 | msecs_to_jiffies(timeout)); | 1626 | msecs_to_jiffies(timeout)); |
1626 | 1627 | ||
1627 | return 0; | 1628 | return 0; |
1628 | } | 1629 | } |
@@ -1799,6 +1800,15 @@ int hci_register_dev(struct hci_dev *hdev) | |||
1799 | goto err; | 1800 | goto err; |
1800 | } | 1801 | } |
1801 | 1802 | ||
1803 | hdev->req_workqueue = alloc_workqueue(hdev->name, | ||
1804 | WQ_HIGHPRI | WQ_UNBOUND | | ||
1805 | WQ_MEM_RECLAIM, 1); | ||
1806 | if (!hdev->req_workqueue) { | ||
1807 | destroy_workqueue(hdev->workqueue); | ||
1808 | error = -ENOMEM; | ||
1809 | goto err; | ||
1810 | } | ||
1811 | |||
1802 | error = hci_add_sysfs(hdev); | 1812 | error = hci_add_sysfs(hdev); |
1803 | if (error < 0) | 1813 | if (error < 0) |
1804 | goto err_wqueue; | 1814 | goto err_wqueue; |
@@ -1821,12 +1831,13 @@ int hci_register_dev(struct hci_dev *hdev) | |||
1821 | hci_notify(hdev, HCI_DEV_REG); | 1831 | hci_notify(hdev, HCI_DEV_REG); |
1822 | hci_dev_hold(hdev); | 1832 | hci_dev_hold(hdev); |
1823 | 1833 | ||
1824 | schedule_work(&hdev->power_on); | 1834 | queue_work(hdev->req_workqueue, &hdev->power_on); |
1825 | 1835 | ||
1826 | return id; | 1836 | return id; |
1827 | 1837 | ||
1828 | err_wqueue: | 1838 | err_wqueue: |
1829 | destroy_workqueue(hdev->workqueue); | 1839 | destroy_workqueue(hdev->workqueue); |
1840 | destroy_workqueue(hdev->req_workqueue); | ||
1830 | err: | 1841 | err: |
1831 | ida_simple_remove(&hci_index_ida, hdev->id); | 1842 | ida_simple_remove(&hci_index_ida, hdev->id); |
1832 | write_lock(&hci_dev_list_lock); | 1843 | write_lock(&hci_dev_list_lock); |
@@ -1880,6 +1891,7 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
1880 | hci_del_sysfs(hdev); | 1891 | hci_del_sysfs(hdev); |
1881 | 1892 | ||
1882 | destroy_workqueue(hdev->workqueue); | 1893 | destroy_workqueue(hdev->workqueue); |
1894 | destroy_workqueue(hdev->req_workqueue); | ||
1883 | 1895 | ||
1884 | hci_dev_lock(hdev); | 1896 | hci_dev_lock(hdev); |
1885 | hci_blacklist_clear(hdev); | 1897 | hci_blacklist_clear(hdev); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 81b44481d0d9..0a4fd642d4b9 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -609,8 +609,17 @@ static void le_setup(struct hci_dev *hdev) | |||
609 | /* Read LE Buffer Size */ | 609 | /* Read LE Buffer Size */ |
610 | hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); | 610 | hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); |
611 | 611 | ||
612 | /* Read LE Local Supported Features */ | ||
613 | hci_send_cmd(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL); | ||
614 | |||
612 | /* Read LE Advertising Channel TX Power */ | 615 | /* Read LE Advertising Channel TX Power */ |
613 | hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); | 616 | hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); |
617 | |||
618 | /* Read LE White List Size */ | ||
619 | hci_send_cmd(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL); | ||
620 | |||
621 | /* Read LE Supported States */ | ||
622 | hci_send_cmd(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); | ||
614 | } | 623 | } |
615 | 624 | ||
616 | static void hci_setup(struct hci_dev *hdev) | 625 | static void hci_setup(struct hci_dev *hdev) |
@@ -1090,6 +1099,19 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, | |||
1090 | hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); | 1099 | hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); |
1091 | } | 1100 | } |
1092 | 1101 | ||
1102 | static void hci_cc_le_read_local_features(struct hci_dev *hdev, | ||
1103 | struct sk_buff *skb) | ||
1104 | { | ||
1105 | struct hci_rp_le_read_local_features *rp = (void *) skb->data; | ||
1106 | |||
1107 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
1108 | |||
1109 | if (!rp->status) | ||
1110 | memcpy(hdev->le_features, rp->features, 8); | ||
1111 | |||
1112 | hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status); | ||
1113 | } | ||
1114 | |||
1093 | static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, | 1115 | static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, |
1094 | struct sk_buff *skb) | 1116 | struct sk_buff *skb) |
1095 | { | 1117 | { |
@@ -1290,6 +1312,19 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
1290 | } | 1312 | } |
1291 | } | 1313 | } |
1292 | 1314 | ||
1315 | static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, | ||
1316 | struct sk_buff *skb) | ||
1317 | { | ||
1318 | struct hci_rp_le_read_white_list_size *rp = (void *) skb->data; | ||
1319 | |||
1320 | BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); | ||
1321 | |||
1322 | if (!rp->status) | ||
1323 | hdev->le_white_list_size = rp->size; | ||
1324 | |||
1325 | hci_req_complete(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, rp->status); | ||
1326 | } | ||
1327 | |||
1293 | static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) | 1328 | static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) |
1294 | { | 1329 | { |
1295 | struct hci_rp_le_ltk_reply *rp = (void *) skb->data; | 1330 | struct hci_rp_le_ltk_reply *rp = (void *) skb->data; |
@@ -1314,6 +1349,19 @@ static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) | |||
1314 | hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); | 1349 | hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); |
1315 | } | 1350 | } |
1316 | 1351 | ||
1352 | static void hci_cc_le_read_supported_states(struct hci_dev *hdev, | ||
1353 | struct sk_buff *skb) | ||
1354 | { | ||
1355 | struct hci_rp_le_read_supported_states *rp = (void *) skb->data; | ||
1356 | |||
1357 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
1358 | |||
1359 | if (!rp->status) | ||
1360 | memcpy(hdev->le_states, rp->le_states, 8); | ||
1361 | |||
1362 | hci_req_complete(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, rp->status); | ||
1363 | } | ||
1364 | |||
1317 | static void hci_cc_write_le_host_supported(struct hci_dev *hdev, | 1365 | static void hci_cc_write_le_host_supported(struct hci_dev *hdev, |
1318 | struct sk_buff *skb) | 1366 | struct sk_buff *skb) |
1319 | { | 1367 | { |
@@ -2628,6 +2676,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2628 | hci_cc_le_read_buffer_size(hdev, skb); | 2676 | hci_cc_le_read_buffer_size(hdev, skb); |
2629 | break; | 2677 | break; |
2630 | 2678 | ||
2679 | case HCI_OP_LE_READ_LOCAL_FEATURES: | ||
2680 | hci_cc_le_read_local_features(hdev, skb); | ||
2681 | break; | ||
2682 | |||
2631 | case HCI_OP_LE_READ_ADV_TX_POWER: | 2683 | case HCI_OP_LE_READ_ADV_TX_POWER: |
2632 | hci_cc_le_read_adv_tx_power(hdev, skb); | 2684 | hci_cc_le_read_adv_tx_power(hdev, skb); |
2633 | break; | 2685 | break; |
@@ -2664,6 +2716,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2664 | hci_cc_le_set_scan_enable(hdev, skb); | 2716 | hci_cc_le_set_scan_enable(hdev, skb); |
2665 | break; | 2717 | break; |
2666 | 2718 | ||
2719 | case HCI_OP_LE_READ_WHITE_LIST_SIZE: | ||
2720 | hci_cc_le_read_white_list_size(hdev, skb); | ||
2721 | break; | ||
2722 | |||
2667 | case HCI_OP_LE_LTK_REPLY: | 2723 | case HCI_OP_LE_LTK_REPLY: |
2668 | hci_cc_le_ltk_reply(hdev, skb); | 2724 | hci_cc_le_ltk_reply(hdev, skb); |
2669 | break; | 2725 | break; |
@@ -2672,6 +2728,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2672 | hci_cc_le_ltk_neg_reply(hdev, skb); | 2728 | hci_cc_le_ltk_neg_reply(hdev, skb); |
2673 | break; | 2729 | break; |
2674 | 2730 | ||
2731 | case HCI_OP_LE_READ_SUPPORTED_STATES: | ||
2732 | hci_cc_le_read_supported_states(hdev, skb); | ||
2733 | break; | ||
2734 | |||
2675 | case HCI_OP_WRITE_LE_HOST_SUPPORTED: | 2735 | case HCI_OP_WRITE_LE_HOST_SUPPORTED: |
2676 | hci_cc_write_le_host_supported(hdev, skb); | 2736 | hci_cc_write_le_host_supported(hdev, skb); |
2677 | break; | 2737 | break; |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 55cceee02a84..23b4e242a31a 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | #include <linux/debugfs.h> | 3 | #include <linux/debugfs.h> |
4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
5 | #include <asm/unaligned.h> | ||
5 | 6 | ||
6 | #include <net/bluetooth/bluetooth.h> | 7 | #include <net/bluetooth/bluetooth.h> |
7 | #include <net/bluetooth/hci_core.h> | 8 | #include <net/bluetooth/hci_core.h> |
@@ -461,19 +462,18 @@ static const struct file_operations blacklist_fops = { | |||
461 | 462 | ||
462 | static void print_bt_uuid(struct seq_file *f, u8 *uuid) | 463 | static void print_bt_uuid(struct seq_file *f, u8 *uuid) |
463 | { | 464 | { |
464 | __be32 data0, data4; | 465 | u32 data0, data5; |
465 | __be16 data1, data2, data3, data5; | 466 | u16 data1, data2, data3, data4; |
466 | 467 | ||
467 | memcpy(&data0, &uuid[0], 4); | 468 | data5 = get_unaligned_le32(uuid); |
468 | memcpy(&data1, &uuid[4], 2); | 469 | data4 = get_unaligned_le16(uuid + 4); |
469 | memcpy(&data2, &uuid[6], 2); | 470 | data3 = get_unaligned_le16(uuid + 6); |
470 | memcpy(&data3, &uuid[8], 2); | 471 | data2 = get_unaligned_le16(uuid + 8); |
471 | memcpy(&data4, &uuid[10], 4); | 472 | data1 = get_unaligned_le16(uuid + 10); |
472 | memcpy(&data5, &uuid[14], 2); | 473 | data0 = get_unaligned_le32(uuid + 12); |
473 | 474 | ||
474 | seq_printf(f, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x\n", | 475 | seq_printf(f, "%.8x-%.4x-%.4x-%.4x-%.4x%.8x\n", |
475 | ntohl(data0), ntohs(data1), ntohs(data2), ntohs(data3), | 476 | data0, data1, data2, data3, data4, data5); |
476 | ntohl(data4), ntohs(data5)); | ||
477 | } | 477 | } |
478 | 478 | ||
479 | static int uuids_show(struct seq_file *f, void *p) | 479 | static int uuids_show(struct seq_file *f, void *p) |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 22e658322845..7c7e9321f1ea 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -1527,17 +1527,12 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) | |||
1527 | BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); | 1527 | BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); |
1528 | 1528 | ||
1529 | switch (hcon->type) { | 1529 | switch (hcon->type) { |
1530 | case AMP_LINK: | ||
1531 | conn->mtu = hcon->hdev->block_mtu; | ||
1532 | break; | ||
1533 | |||
1534 | case LE_LINK: | 1530 | case LE_LINK: |
1535 | if (hcon->hdev->le_mtu) { | 1531 | if (hcon->hdev->le_mtu) { |
1536 | conn->mtu = hcon->hdev->le_mtu; | 1532 | conn->mtu = hcon->hdev->le_mtu; |
1537 | break; | 1533 | break; |
1538 | } | 1534 | } |
1539 | /* fall through */ | 1535 | /* fall through */ |
1540 | |||
1541 | default: | 1536 | default: |
1542 | conn->mtu = hcon->hdev->acl_mtu; | 1537 | conn->mtu = hcon->hdev->acl_mtu; |
1543 | break; | 1538 | break; |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f559b966279c..e7f944f52ff2 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -777,14 +777,19 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, | |||
777 | 777 | ||
778 | BT_DBG("request for %s", hdev->name); | 778 | BT_DBG("request for %s", hdev->name); |
779 | 779 | ||
780 | if (cp->val != 0x00 && cp->val != 0x01) | ||
781 | return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED, | ||
782 | MGMT_STATUS_INVALID_PARAMS); | ||
783 | |||
780 | hci_dev_lock(hdev); | 784 | hci_dev_lock(hdev); |
781 | 785 | ||
782 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { | 786 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { |
783 | cancel_delayed_work(&hdev->power_off); | 787 | cancel_delayed_work(&hdev->power_off); |
784 | 788 | ||
785 | if (cp->val) { | 789 | if (cp->val) { |
786 | err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev); | 790 | mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, |
787 | mgmt_powered(hdev, 1); | 791 | data, len); |
792 | err = mgmt_powered(hdev, 1); | ||
788 | goto failed; | 793 | goto failed; |
789 | } | 794 | } |
790 | } | 795 | } |
@@ -807,9 +812,9 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, | |||
807 | } | 812 | } |
808 | 813 | ||
809 | if (cp->val) | 814 | if (cp->val) |
810 | schedule_work(&hdev->power_on); | 815 | queue_work(hdev->req_workqueue, &hdev->power_on); |
811 | else | 816 | else |
812 | schedule_work(&hdev->power_off.work); | 817 | queue_work(hdev->req_workqueue, &hdev->power_off.work); |
813 | 818 | ||
814 | err = 0; | 819 | err = 0; |
815 | 820 | ||
@@ -872,6 +877,10 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
872 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | 877 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, |
873 | MGMT_STATUS_NOT_SUPPORTED); | 878 | MGMT_STATUS_NOT_SUPPORTED); |
874 | 879 | ||
880 | if (cp->val != 0x00 && cp->val != 0x01) | ||
881 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | ||
882 | MGMT_STATUS_INVALID_PARAMS); | ||
883 | |||
875 | timeout = __le16_to_cpu(cp->timeout); | 884 | timeout = __le16_to_cpu(cp->timeout); |
876 | if (!cp->val && timeout > 0) | 885 | if (!cp->val && timeout > 0) |
877 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | 886 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, |
@@ -971,6 +980,10 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
971 | return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, | 980 | return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, |
972 | MGMT_STATUS_NOT_SUPPORTED); | 981 | MGMT_STATUS_NOT_SUPPORTED); |
973 | 982 | ||
983 | if (cp->val != 0x00 && cp->val != 0x01) | ||
984 | return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, | ||
985 | MGMT_STATUS_INVALID_PARAMS); | ||
986 | |||
974 | hci_dev_lock(hdev); | 987 | hci_dev_lock(hdev); |
975 | 988 | ||
976 | if (!hdev_is_powered(hdev)) { | 989 | if (!hdev_is_powered(hdev)) { |
@@ -1041,6 +1054,10 @@ static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1041 | 1054 | ||
1042 | BT_DBG("request for %s", hdev->name); | 1055 | BT_DBG("request for %s", hdev->name); |
1043 | 1056 | ||
1057 | if (cp->val != 0x00 && cp->val != 0x01) | ||
1058 | return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE, | ||
1059 | MGMT_STATUS_INVALID_PARAMS); | ||
1060 | |||
1044 | hci_dev_lock(hdev); | 1061 | hci_dev_lock(hdev); |
1045 | 1062 | ||
1046 | if (cp->val) | 1063 | if (cp->val) |
@@ -1073,6 +1090,10 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1073 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY, | 1090 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY, |
1074 | MGMT_STATUS_NOT_SUPPORTED); | 1091 | MGMT_STATUS_NOT_SUPPORTED); |
1075 | 1092 | ||
1093 | if (cp->val != 0x00 && cp->val != 0x01) | ||
1094 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY, | ||
1095 | MGMT_STATUS_INVALID_PARAMS); | ||
1096 | |||
1076 | hci_dev_lock(hdev); | 1097 | hci_dev_lock(hdev); |
1077 | 1098 | ||
1078 | if (!hdev_is_powered(hdev)) { | 1099 | if (!hdev_is_powered(hdev)) { |
@@ -1133,13 +1154,15 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1133 | 1154 | ||
1134 | BT_DBG("request for %s", hdev->name); | 1155 | BT_DBG("request for %s", hdev->name); |
1135 | 1156 | ||
1136 | hci_dev_lock(hdev); | 1157 | if (!lmp_ssp_capable(hdev)) |
1158 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, | ||
1159 | MGMT_STATUS_NOT_SUPPORTED); | ||
1137 | 1160 | ||
1138 | if (!lmp_ssp_capable(hdev)) { | 1161 | if (cp->val != 0x00 && cp->val != 0x01) |
1139 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, | 1162 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, |
1140 | MGMT_STATUS_NOT_SUPPORTED); | 1163 | MGMT_STATUS_INVALID_PARAMS); |
1141 | goto failed; | 1164 | |
1142 | } | 1165 | hci_dev_lock(hdev); |
1143 | 1166 | ||
1144 | val = !!cp->val; | 1167 | val = !!cp->val; |
1145 | 1168 | ||
@@ -1199,6 +1222,10 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1199 | return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, | 1222 | return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, |
1200 | MGMT_STATUS_NOT_SUPPORTED); | 1223 | MGMT_STATUS_NOT_SUPPORTED); |
1201 | 1224 | ||
1225 | if (cp->val != 0x00 && cp->val != 0x01) | ||
1226 | return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, | ||
1227 | MGMT_STATUS_INVALID_PARAMS); | ||
1228 | |||
1202 | if (cp->val) | 1229 | if (cp->val) |
1203 | set_bit(HCI_HS_ENABLED, &hdev->dev_flags); | 1230 | set_bit(HCI_HS_ENABLED, &hdev->dev_flags); |
1204 | else | 1231 | else |
@@ -1217,13 +1244,15 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1217 | 1244 | ||
1218 | BT_DBG("request for %s", hdev->name); | 1245 | BT_DBG("request for %s", hdev->name); |
1219 | 1246 | ||
1220 | hci_dev_lock(hdev); | 1247 | if (!lmp_le_capable(hdev)) |
1248 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LE, | ||
1249 | MGMT_STATUS_NOT_SUPPORTED); | ||
1221 | 1250 | ||
1222 | if (!lmp_le_capable(hdev)) { | 1251 | if (cp->val != 0x00 && cp->val != 0x01) |
1223 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE, | 1252 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LE, |
1224 | MGMT_STATUS_NOT_SUPPORTED); | 1253 | MGMT_STATUS_INVALID_PARAMS); |
1225 | goto unlock; | 1254 | |
1226 | } | 1255 | hci_dev_lock(hdev); |
1227 | 1256 | ||
1228 | val = !!cp->val; | 1257 | val = !!cp->val; |
1229 | enabled = lmp_host_le_capable(hdev); | 1258 | enabled = lmp_host_le_capable(hdev); |
@@ -1332,7 +1361,8 @@ static bool enable_service_cache(struct hci_dev *hdev) | |||
1332 | return false; | 1361 | return false; |
1333 | 1362 | ||
1334 | if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) { | 1363 | if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) { |
1335 | schedule_delayed_work(&hdev->service_cache, CACHE_TIMEOUT); | 1364 | queue_delayed_work(hdev->workqueue, &hdev->service_cache, |
1365 | CACHE_TIMEOUT); | ||
1336 | return true; | 1366 | return true; |
1337 | } | 1367 | } |
1338 | 1368 | ||
@@ -1422,13 +1452,19 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1422 | 1452 | ||
1423 | BT_DBG("request for %s", hdev->name); | 1453 | BT_DBG("request for %s", hdev->name); |
1424 | 1454 | ||
1425 | hci_dev_lock(hdev); | 1455 | if (!lmp_bredr_capable(hdev)) |
1456 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | ||
1457 | MGMT_STATUS_NOT_SUPPORTED); | ||
1426 | 1458 | ||
1427 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | 1459 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) |
1428 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | 1460 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, |
1429 | MGMT_STATUS_BUSY); | 1461 | MGMT_STATUS_BUSY); |
1430 | goto unlock; | 1462 | |
1431 | } | 1463 | if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) |
1464 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | ||
1465 | MGMT_STATUS_INVALID_PARAMS); | ||
1466 | |||
1467 | hci_dev_lock(hdev); | ||
1432 | 1468 | ||
1433 | hdev->major_class = cp->major; | 1469 | hdev->major_class = cp->major; |
1434 | hdev->minor_class = cp->minor; | 1470 | hdev->minor_class = cp->minor; |
@@ -1483,9 +1519,21 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1483 | MGMT_STATUS_INVALID_PARAMS); | 1519 | MGMT_STATUS_INVALID_PARAMS); |
1484 | } | 1520 | } |
1485 | 1521 | ||
1522 | if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01) | ||
1523 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, | ||
1524 | MGMT_STATUS_INVALID_PARAMS); | ||
1525 | |||
1486 | BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys, | 1526 | BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys, |
1487 | key_count); | 1527 | key_count); |
1488 | 1528 | ||
1529 | for (i = 0; i < key_count; i++) { | ||
1530 | struct mgmt_link_key_info *key = &cp->keys[i]; | ||
1531 | |||
1532 | if (key->addr.type != BDADDR_BREDR) | ||
1533 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, | ||
1534 | MGMT_STATUS_INVALID_PARAMS); | ||
1535 | } | ||
1536 | |||
1489 | hci_dev_lock(hdev); | 1537 | hci_dev_lock(hdev); |
1490 | 1538 | ||
1491 | hci_link_keys_clear(hdev); | 1539 | hci_link_keys_clear(hdev); |
@@ -1533,12 +1581,22 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1533 | struct hci_conn *conn; | 1581 | struct hci_conn *conn; |
1534 | int err; | 1582 | int err; |
1535 | 1583 | ||
1536 | hci_dev_lock(hdev); | ||
1537 | |||
1538 | memset(&rp, 0, sizeof(rp)); | 1584 | memset(&rp, 0, sizeof(rp)); |
1539 | bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); | 1585 | bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); |
1540 | rp.addr.type = cp->addr.type; | 1586 | rp.addr.type = cp->addr.type; |
1541 | 1587 | ||
1588 | if (!bdaddr_type_is_valid(cp->addr.type)) | ||
1589 | return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, | ||
1590 | MGMT_STATUS_INVALID_PARAMS, | ||
1591 | &rp, sizeof(rp)); | ||
1592 | |||
1593 | if (cp->disconnect != 0x00 && cp->disconnect != 0x01) | ||
1594 | return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, | ||
1595 | MGMT_STATUS_INVALID_PARAMS, | ||
1596 | &rp, sizeof(rp)); | ||
1597 | |||
1598 | hci_dev_lock(hdev); | ||
1599 | |||
1542 | if (!hdev_is_powered(hdev)) { | 1600 | if (!hdev_is_powered(hdev)) { |
1543 | err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, | 1601 | err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, |
1544 | MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); | 1602 | MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); |
@@ -1596,6 +1654,7 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1596 | u16 len) | 1654 | u16 len) |
1597 | { | 1655 | { |
1598 | struct mgmt_cp_disconnect *cp = data; | 1656 | struct mgmt_cp_disconnect *cp = data; |
1657 | struct mgmt_rp_disconnect rp; | ||
1599 | struct hci_cp_disconnect dc; | 1658 | struct hci_cp_disconnect dc; |
1600 | struct pending_cmd *cmd; | 1659 | struct pending_cmd *cmd; |
1601 | struct hci_conn *conn; | 1660 | struct hci_conn *conn; |
@@ -1603,17 +1662,26 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1603 | 1662 | ||
1604 | BT_DBG(""); | 1663 | BT_DBG(""); |
1605 | 1664 | ||
1665 | memset(&rp, 0, sizeof(rp)); | ||
1666 | bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); | ||
1667 | rp.addr.type = cp->addr.type; | ||
1668 | |||
1669 | if (!bdaddr_type_is_valid(cp->addr.type)) | ||
1670 | return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, | ||
1671 | MGMT_STATUS_INVALID_PARAMS, | ||
1672 | &rp, sizeof(rp)); | ||
1673 | |||
1606 | hci_dev_lock(hdev); | 1674 | hci_dev_lock(hdev); |
1607 | 1675 | ||
1608 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1676 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1609 | err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT, | 1677 | err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, |
1610 | MGMT_STATUS_NOT_POWERED); | 1678 | MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); |
1611 | goto failed; | 1679 | goto failed; |
1612 | } | 1680 | } |
1613 | 1681 | ||
1614 | if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) { | 1682 | if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) { |
1615 | err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT, | 1683 | err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, |
1616 | MGMT_STATUS_BUSY); | 1684 | MGMT_STATUS_BUSY, &rp, sizeof(rp)); |
1617 | goto failed; | 1685 | goto failed; |
1618 | } | 1686 | } |
1619 | 1687 | ||
@@ -1624,8 +1692,8 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1624 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); | 1692 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); |
1625 | 1693 | ||
1626 | if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) { | 1694 | if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) { |
1627 | err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT, | 1695 | err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, |
1628 | MGMT_STATUS_NOT_CONNECTED); | 1696 | MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp)); |
1629 | goto failed; | 1697 | goto failed; |
1630 | } | 1698 | } |
1631 | 1699 | ||
@@ -1903,11 +1971,20 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1903 | 1971 | ||
1904 | BT_DBG(""); | 1972 | BT_DBG(""); |
1905 | 1973 | ||
1974 | memset(&rp, 0, sizeof(rp)); | ||
1975 | bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); | ||
1976 | rp.addr.type = cp->addr.type; | ||
1977 | |||
1978 | if (!bdaddr_type_is_valid(cp->addr.type)) | ||
1979 | return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE, | ||
1980 | MGMT_STATUS_INVALID_PARAMS, | ||
1981 | &rp, sizeof(rp)); | ||
1982 | |||
1906 | hci_dev_lock(hdev); | 1983 | hci_dev_lock(hdev); |
1907 | 1984 | ||
1908 | if (!hdev_is_powered(hdev)) { | 1985 | if (!hdev_is_powered(hdev)) { |
1909 | err = cmd_status(sk, hdev->id, MGMT_OP_PAIR_DEVICE, | 1986 | err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE, |
1910 | MGMT_STATUS_NOT_POWERED); | 1987 | MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); |
1911 | goto unlock; | 1988 | goto unlock; |
1912 | } | 1989 | } |
1913 | 1990 | ||
@@ -1924,10 +2001,6 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1924 | conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, | 2001 | conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, |
1925 | cp->addr.type, sec_level, auth_type); | 2002 | cp->addr.type, sec_level, auth_type); |
1926 | 2003 | ||
1927 | memset(&rp, 0, sizeof(rp)); | ||
1928 | bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); | ||
1929 | rp.addr.type = cp->addr.type; | ||
1930 | |||
1931 | if (IS_ERR(conn)) { | 2004 | if (IS_ERR(conn)) { |
1932 | int status; | 2005 | int status; |
1933 | 2006 | ||
@@ -2254,24 +2327,16 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, | |||
2254 | 2327 | ||
2255 | hci_dev_lock(hdev); | 2328 | hci_dev_lock(hdev); |
2256 | 2329 | ||
2257 | if (!hdev_is_powered(hdev)) { | ||
2258 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, | ||
2259 | MGMT_STATUS_NOT_POWERED, &cp->addr, | ||
2260 | sizeof(cp->addr)); | ||
2261 | goto unlock; | ||
2262 | } | ||
2263 | |||
2264 | err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr, cp->hash, | 2330 | err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr, cp->hash, |
2265 | cp->randomizer); | 2331 | cp->randomizer); |
2266 | if (err < 0) | 2332 | if (err < 0) |
2267 | status = MGMT_STATUS_FAILED; | 2333 | status = MGMT_STATUS_FAILED; |
2268 | else | 2334 | else |
2269 | status = 0; | 2335 | status = MGMT_STATUS_SUCCESS; |
2270 | 2336 | ||
2271 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, status, | 2337 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, status, |
2272 | &cp->addr, sizeof(cp->addr)); | 2338 | &cp->addr, sizeof(cp->addr)); |
2273 | 2339 | ||
2274 | unlock: | ||
2275 | hci_dev_unlock(hdev); | 2340 | hci_dev_unlock(hdev); |
2276 | return err; | 2341 | return err; |
2277 | } | 2342 | } |
@@ -2287,24 +2352,15 @@ static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev, | |||
2287 | 2352 | ||
2288 | hci_dev_lock(hdev); | 2353 | hci_dev_lock(hdev); |
2289 | 2354 | ||
2290 | if (!hdev_is_powered(hdev)) { | ||
2291 | err = cmd_complete(sk, hdev->id, | ||
2292 | MGMT_OP_REMOVE_REMOTE_OOB_DATA, | ||
2293 | MGMT_STATUS_NOT_POWERED, &cp->addr, | ||
2294 | sizeof(cp->addr)); | ||
2295 | goto unlock; | ||
2296 | } | ||
2297 | |||
2298 | err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr); | 2355 | err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr); |
2299 | if (err < 0) | 2356 | if (err < 0) |
2300 | status = MGMT_STATUS_INVALID_PARAMS; | 2357 | status = MGMT_STATUS_INVALID_PARAMS; |
2301 | else | 2358 | else |
2302 | status = 0; | 2359 | status = MGMT_STATUS_SUCCESS; |
2303 | 2360 | ||
2304 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA, | 2361 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA, |
2305 | status, &cp->addr, sizeof(cp->addr)); | 2362 | status, &cp->addr, sizeof(cp->addr)); |
2306 | 2363 | ||
2307 | unlock: | ||
2308 | hci_dev_unlock(hdev); | 2364 | hci_dev_unlock(hdev); |
2309 | return err; | 2365 | return err; |
2310 | } | 2366 | } |
@@ -2365,31 +2421,45 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
2365 | 2421 | ||
2366 | switch (hdev->discovery.type) { | 2422 | switch (hdev->discovery.type) { |
2367 | case DISCOV_TYPE_BREDR: | 2423 | case DISCOV_TYPE_BREDR: |
2368 | if (lmp_bredr_capable(hdev)) | 2424 | if (!lmp_bredr_capable(hdev)) { |
2369 | err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR); | 2425 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
2370 | else | 2426 | MGMT_STATUS_NOT_SUPPORTED); |
2371 | err = -ENOTSUPP; | 2427 | mgmt_pending_remove(cmd); |
2428 | goto failed; | ||
2429 | } | ||
2430 | |||
2431 | err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR); | ||
2372 | break; | 2432 | break; |
2373 | 2433 | ||
2374 | case DISCOV_TYPE_LE: | 2434 | case DISCOV_TYPE_LE: |
2375 | if (lmp_host_le_capable(hdev)) | 2435 | if (!lmp_host_le_capable(hdev)) { |
2376 | err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT, | 2436 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
2377 | LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY); | 2437 | MGMT_STATUS_NOT_SUPPORTED); |
2378 | else | 2438 | mgmt_pending_remove(cmd); |
2379 | err = -ENOTSUPP; | 2439 | goto failed; |
2440 | } | ||
2441 | |||
2442 | err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT, | ||
2443 | LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY); | ||
2380 | break; | 2444 | break; |
2381 | 2445 | ||
2382 | case DISCOV_TYPE_INTERLEAVED: | 2446 | case DISCOV_TYPE_INTERLEAVED: |
2383 | if (lmp_host_le_capable(hdev) && lmp_bredr_capable(hdev)) | 2447 | if (!lmp_host_le_capable(hdev) || !lmp_bredr_capable(hdev)) { |
2384 | err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT, | 2448 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
2385 | LE_SCAN_WIN, | 2449 | MGMT_STATUS_NOT_SUPPORTED); |
2386 | LE_SCAN_TIMEOUT_BREDR_LE); | 2450 | mgmt_pending_remove(cmd); |
2387 | else | 2451 | goto failed; |
2388 | err = -ENOTSUPP; | 2452 | } |
2453 | |||
2454 | err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT, LE_SCAN_WIN, | ||
2455 | LE_SCAN_TIMEOUT_BREDR_LE); | ||
2389 | break; | 2456 | break; |
2390 | 2457 | ||
2391 | default: | 2458 | default: |
2392 | err = -EINVAL; | 2459 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
2460 | MGMT_STATUS_INVALID_PARAMS); | ||
2461 | mgmt_pending_remove(cmd); | ||
2462 | goto failed; | ||
2393 | } | 2463 | } |
2394 | 2464 | ||
2395 | if (err < 0) | 2465 | if (err < 0) |
@@ -2510,7 +2580,8 @@ static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2510 | hci_inquiry_cache_update_resolve(hdev, e); | 2580 | hci_inquiry_cache_update_resolve(hdev, e); |
2511 | } | 2581 | } |
2512 | 2582 | ||
2513 | err = 0; | 2583 | err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr, |
2584 | sizeof(cp->addr)); | ||
2514 | 2585 | ||
2515 | failed: | 2586 | failed: |
2516 | hci_dev_unlock(hdev); | 2587 | hci_dev_unlock(hdev); |
@@ -2526,13 +2597,18 @@ static int block_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2526 | 2597 | ||
2527 | BT_DBG("%s", hdev->name); | 2598 | BT_DBG("%s", hdev->name); |
2528 | 2599 | ||
2600 | if (!bdaddr_type_is_valid(cp->addr.type)) | ||
2601 | return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, | ||
2602 | MGMT_STATUS_INVALID_PARAMS, | ||
2603 | &cp->addr, sizeof(cp->addr)); | ||
2604 | |||
2529 | hci_dev_lock(hdev); | 2605 | hci_dev_lock(hdev); |
2530 | 2606 | ||
2531 | err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type); | 2607 | err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type); |
2532 | if (err < 0) | 2608 | if (err < 0) |
2533 | status = MGMT_STATUS_FAILED; | 2609 | status = MGMT_STATUS_FAILED; |
2534 | else | 2610 | else |
2535 | status = 0; | 2611 | status = MGMT_STATUS_SUCCESS; |
2536 | 2612 | ||
2537 | err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status, | 2613 | err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status, |
2538 | &cp->addr, sizeof(cp->addr)); | 2614 | &cp->addr, sizeof(cp->addr)); |
@@ -2551,13 +2627,18 @@ static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2551 | 2627 | ||
2552 | BT_DBG("%s", hdev->name); | 2628 | BT_DBG("%s", hdev->name); |
2553 | 2629 | ||
2630 | if (!bdaddr_type_is_valid(cp->addr.type)) | ||
2631 | return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, | ||
2632 | MGMT_STATUS_INVALID_PARAMS, | ||
2633 | &cp->addr, sizeof(cp->addr)); | ||
2634 | |||
2554 | hci_dev_lock(hdev); | 2635 | hci_dev_lock(hdev); |
2555 | 2636 | ||
2556 | err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type); | 2637 | err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type); |
2557 | if (err < 0) | 2638 | if (err < 0) |
2558 | status = MGMT_STATUS_INVALID_PARAMS; | 2639 | status = MGMT_STATUS_INVALID_PARAMS; |
2559 | else | 2640 | else |
2560 | status = 0; | 2641 | status = MGMT_STATUS_SUCCESS; |
2561 | 2642 | ||
2562 | err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status, | 2643 | err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status, |
2563 | &cp->addr, sizeof(cp->addr)); | 2644 | &cp->addr, sizeof(cp->addr)); |
@@ -2612,6 +2693,10 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, | |||
2612 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | 2693 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
2613 | MGMT_STATUS_NOT_SUPPORTED); | 2694 | MGMT_STATUS_NOT_SUPPORTED); |
2614 | 2695 | ||
2696 | if (cp->val != 0x00 && cp->val != 0x01) | ||
2697 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | ||
2698 | MGMT_STATUS_INVALID_PARAMS); | ||
2699 | |||
2615 | if (!hdev_is_powered(hdev)) | 2700 | if (!hdev_is_powered(hdev)) |
2616 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | 2701 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
2617 | MGMT_STATUS_NOT_POWERED); | 2702 | MGMT_STATUS_NOT_POWERED); |
@@ -2659,12 +2744,23 @@ done: | |||
2659 | return err; | 2744 | return err; |
2660 | } | 2745 | } |
2661 | 2746 | ||
2747 | static bool ltk_is_valid(struct mgmt_ltk_info *key) | ||
2748 | { | ||
2749 | if (key->authenticated != 0x00 && key->authenticated != 0x01) | ||
2750 | return false; | ||
2751 | if (key->master != 0x00 && key->master != 0x01) | ||
2752 | return false; | ||
2753 | if (!bdaddr_type_is_le(key->addr.type)) | ||
2754 | return false; | ||
2755 | return true; | ||
2756 | } | ||
2757 | |||
2662 | static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | 2758 | static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, |
2663 | void *cp_data, u16 len) | 2759 | void *cp_data, u16 len) |
2664 | { | 2760 | { |
2665 | struct mgmt_cp_load_long_term_keys *cp = cp_data; | 2761 | struct mgmt_cp_load_long_term_keys *cp = cp_data; |
2666 | u16 key_count, expected_len; | 2762 | u16 key_count, expected_len; |
2667 | int i; | 2763 | int i, err; |
2668 | 2764 | ||
2669 | key_count = __le16_to_cpu(cp->key_count); | 2765 | key_count = __le16_to_cpu(cp->key_count); |
2670 | 2766 | ||
@@ -2674,11 +2770,20 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | |||
2674 | BT_ERR("load_keys: expected %u bytes, got %u bytes", | 2770 | BT_ERR("load_keys: expected %u bytes, got %u bytes", |
2675 | len, expected_len); | 2771 | len, expected_len); |
2676 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, | 2772 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, |
2677 | EINVAL); | 2773 | MGMT_STATUS_INVALID_PARAMS); |
2678 | } | 2774 | } |
2679 | 2775 | ||
2680 | BT_DBG("%s key_count %u", hdev->name, key_count); | 2776 | BT_DBG("%s key_count %u", hdev->name, key_count); |
2681 | 2777 | ||
2778 | for (i = 0; i < key_count; i++) { | ||
2779 | struct mgmt_ltk_info *key = &cp->keys[i]; | ||
2780 | |||
2781 | if (!ltk_is_valid(key)) | ||
2782 | return cmd_status(sk, hdev->id, | ||
2783 | MGMT_OP_LOAD_LONG_TERM_KEYS, | ||
2784 | MGMT_STATUS_INVALID_PARAMS); | ||
2785 | } | ||
2786 | |||
2682 | hci_dev_lock(hdev); | 2787 | hci_dev_lock(hdev); |
2683 | 2788 | ||
2684 | hci_smp_ltks_clear(hdev); | 2789 | hci_smp_ltks_clear(hdev); |
@@ -2698,9 +2803,12 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | |||
2698 | key->enc_size, key->ediv, key->rand); | 2803 | key->enc_size, key->ediv, key->rand); |
2699 | } | 2804 | } |
2700 | 2805 | ||
2806 | err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0, | ||
2807 | NULL, 0); | ||
2808 | |||
2701 | hci_dev_unlock(hdev); | 2809 | hci_dev_unlock(hdev); |
2702 | 2810 | ||
2703 | return 0; | 2811 | return err; |
2704 | } | 2812 | } |
2705 | 2813 | ||
2706 | static const struct mgmt_handler { | 2814 | static const struct mgmt_handler { |
@@ -2946,7 +3054,13 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) | |||
2946 | } | 3054 | } |
2947 | } else { | 3055 | } else { |
2948 | u8 status = MGMT_STATUS_NOT_POWERED; | 3056 | u8 status = MGMT_STATUS_NOT_POWERED; |
3057 | u8 zero_cod[] = { 0, 0, 0 }; | ||
3058 | |||
2949 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | 3059 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); |
3060 | |||
3061 | if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) | ||
3062 | mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, | ||
3063 | zero_cod, sizeof(zero_cod), NULL); | ||
2950 | } | 3064 | } |
2951 | 3065 | ||
2952 | err = new_settings(hdev, match.sk); | 3066 | err = new_settings(hdev, match.sk); |