diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-02-08 13:16:17 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-02-08 13:16:17 -0500 |
commit | f5237f278f30a92401539a54f87ee0c717b6f818 (patch) | |
tree | 209d4fd6fb00e660c76ca8ac5d4caed59dbb9957 /net/bluetooth | |
parent | b285109dde7b873b5dc671ef1b3ae3090f4bc72f (diff) | |
parent | b26f5f09ebdeb85ab152344cc1d6d484a3ce967d (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
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 | 30 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 64 | ||||
-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 | 489 | ||||
-rw-r--r-- | net/bluetooth/sco.c | 18 |
9 files changed, 476 insertions, 220 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..22e77a786545 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); |
@@ -1182,14 +1183,10 @@ static void hci_discov_off(struct work_struct *work) | |||
1182 | 1183 | ||
1183 | int hci_uuids_clear(struct hci_dev *hdev) | 1184 | int hci_uuids_clear(struct hci_dev *hdev) |
1184 | { | 1185 | { |
1185 | struct list_head *p, *n; | 1186 | struct bt_uuid *uuid, *tmp; |
1186 | |||
1187 | list_for_each_safe(p, n, &hdev->uuids) { | ||
1188 | struct bt_uuid *uuid; | ||
1189 | 1187 | ||
1190 | uuid = list_entry(p, struct bt_uuid, list); | 1188 | list_for_each_entry_safe(uuid, tmp, &hdev->uuids, list) { |
1191 | 1189 | list_del(&uuid->list); | |
1192 | list_del(p); | ||
1193 | kfree(uuid); | 1190 | kfree(uuid); |
1194 | } | 1191 | } |
1195 | 1192 | ||
@@ -1621,8 +1618,8 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval, | |||
1621 | if (err < 0) | 1618 | if (err < 0) |
1622 | return err; | 1619 | return err; |
1623 | 1620 | ||
1624 | schedule_delayed_work(&hdev->le_scan_disable, | 1621 | queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, |
1625 | msecs_to_jiffies(timeout)); | 1622 | msecs_to_jiffies(timeout)); |
1626 | 1623 | ||
1627 | return 0; | 1624 | return 0; |
1628 | } | 1625 | } |
@@ -1799,6 +1796,15 @@ int hci_register_dev(struct hci_dev *hdev) | |||
1799 | goto err; | 1796 | goto err; |
1800 | } | 1797 | } |
1801 | 1798 | ||
1799 | hdev->req_workqueue = alloc_workqueue(hdev->name, | ||
1800 | WQ_HIGHPRI | WQ_UNBOUND | | ||
1801 | WQ_MEM_RECLAIM, 1); | ||
1802 | if (!hdev->req_workqueue) { | ||
1803 | destroy_workqueue(hdev->workqueue); | ||
1804 | error = -ENOMEM; | ||
1805 | goto err; | ||
1806 | } | ||
1807 | |||
1802 | error = hci_add_sysfs(hdev); | 1808 | error = hci_add_sysfs(hdev); |
1803 | if (error < 0) | 1809 | if (error < 0) |
1804 | goto err_wqueue; | 1810 | goto err_wqueue; |
@@ -1821,12 +1827,13 @@ int hci_register_dev(struct hci_dev *hdev) | |||
1821 | hci_notify(hdev, HCI_DEV_REG); | 1827 | hci_notify(hdev, HCI_DEV_REG); |
1822 | hci_dev_hold(hdev); | 1828 | hci_dev_hold(hdev); |
1823 | 1829 | ||
1824 | schedule_work(&hdev->power_on); | 1830 | queue_work(hdev->req_workqueue, &hdev->power_on); |
1825 | 1831 | ||
1826 | return id; | 1832 | return id; |
1827 | 1833 | ||
1828 | err_wqueue: | 1834 | err_wqueue: |
1829 | destroy_workqueue(hdev->workqueue); | 1835 | destroy_workqueue(hdev->workqueue); |
1836 | destroy_workqueue(hdev->req_workqueue); | ||
1830 | err: | 1837 | err: |
1831 | ida_simple_remove(&hci_index_ida, hdev->id); | 1838 | ida_simple_remove(&hci_index_ida, hdev->id); |
1832 | write_lock(&hci_dev_list_lock); | 1839 | write_lock(&hci_dev_list_lock); |
@@ -1880,6 +1887,7 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
1880 | hci_del_sysfs(hdev); | 1887 | hci_del_sysfs(hdev); |
1881 | 1888 | ||
1882 | destroy_workqueue(hdev->workqueue); | 1889 | destroy_workqueue(hdev->workqueue); |
1890 | destroy_workqueue(hdev->req_workqueue); | ||
1883 | 1891 | ||
1884 | hci_dev_lock(hdev); | 1892 | hci_dev_lock(hdev); |
1885 | hci_blacklist_clear(hdev); | 1893 | hci_blacklist_clear(hdev); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 81b44481d0d9..477726a63512 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; |
@@ -3928,8 +3988,6 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3928 | void *ptr = &skb->data[1]; | 3988 | void *ptr = &skb->data[1]; |
3929 | s8 rssi; | 3989 | s8 rssi; |
3930 | 3990 | ||
3931 | hci_dev_lock(hdev); | ||
3932 | |||
3933 | while (num_reports--) { | 3991 | while (num_reports--) { |
3934 | struct hci_ev_le_advertising_info *ev = ptr; | 3992 | struct hci_ev_le_advertising_info *ev = ptr; |
3935 | 3993 | ||
@@ -3939,8 +3997,6 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3939 | 3997 | ||
3940 | ptr += sizeof(*ev) + ev->length + 1; | 3998 | ptr += sizeof(*ev) + ev->length + 1; |
3941 | } | 3999 | } |
3942 | |||
3943 | hci_dev_unlock(hdev); | ||
3944 | } | 4000 | } |
3945 | 4001 | ||
3946 | static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | 4002 | static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
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..39395c7144aa 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -35,7 +35,7 @@ | |||
35 | bool enable_hs; | 35 | bool enable_hs; |
36 | 36 | ||
37 | #define MGMT_VERSION 1 | 37 | #define MGMT_VERSION 1 |
38 | #define MGMT_REVISION 2 | 38 | #define MGMT_REVISION 3 |
39 | 39 | ||
40 | static const u16 mgmt_commands[] = { | 40 | static const u16 mgmt_commands[] = { |
41 | MGMT_OP_READ_INDEX_LIST, | 41 | MGMT_OP_READ_INDEX_LIST, |
@@ -435,35 +435,117 @@ static u32 get_current_settings(struct hci_dev *hdev) | |||
435 | 435 | ||
436 | #define PNP_INFO_SVCLASS_ID 0x1200 | 436 | #define PNP_INFO_SVCLASS_ID 0x1200 |
437 | 437 | ||
438 | static u8 bluetooth_base_uuid[] = { | 438 | static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) |
439 | 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, | 439 | { |
440 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 440 | u8 *ptr = data, *uuids_start = NULL; |
441 | }; | 441 | struct bt_uuid *uuid; |
442 | |||
443 | if (len < 4) | ||
444 | return ptr; | ||
445 | |||
446 | list_for_each_entry(uuid, &hdev->uuids, list) { | ||
447 | u16 uuid16; | ||
448 | |||
449 | if (uuid->size != 16) | ||
450 | continue; | ||
451 | |||
452 | uuid16 = get_unaligned_le16(&uuid->uuid[12]); | ||
453 | if (uuid16 < 0x1100) | ||
454 | continue; | ||
455 | |||
456 | if (uuid16 == PNP_INFO_SVCLASS_ID) | ||
457 | continue; | ||
442 | 458 | ||
443 | static u16 get_uuid16(u8 *uuid128) | 459 | if (!uuids_start) { |
460 | uuids_start = ptr; | ||
461 | uuids_start[0] = 1; | ||
462 | uuids_start[1] = EIR_UUID16_ALL; | ||
463 | ptr += 2; | ||
464 | } | ||
465 | |||
466 | /* Stop if not enough space to put next UUID */ | ||
467 | if ((ptr - data) + sizeof(u16) > len) { | ||
468 | uuids_start[1] = EIR_UUID16_SOME; | ||
469 | break; | ||
470 | } | ||
471 | |||
472 | *ptr++ = (uuid16 & 0x00ff); | ||
473 | *ptr++ = (uuid16 & 0xff00) >> 8; | ||
474 | uuids_start[0] += sizeof(uuid16); | ||
475 | } | ||
476 | |||
477 | return ptr; | ||
478 | } | ||
479 | |||
480 | static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) | ||
444 | { | 481 | { |
445 | u32 val; | 482 | u8 *ptr = data, *uuids_start = NULL; |
446 | int i; | 483 | struct bt_uuid *uuid; |
484 | |||
485 | if (len < 6) | ||
486 | return ptr; | ||
447 | 487 | ||
448 | for (i = 0; i < 12; i++) { | 488 | list_for_each_entry(uuid, &hdev->uuids, list) { |
449 | if (bluetooth_base_uuid[i] != uuid128[i]) | 489 | if (uuid->size != 32) |
450 | return 0; | 490 | continue; |
491 | |||
492 | if (!uuids_start) { | ||
493 | uuids_start = ptr; | ||
494 | uuids_start[0] = 1; | ||
495 | uuids_start[1] = EIR_UUID32_ALL; | ||
496 | ptr += 2; | ||
497 | } | ||
498 | |||
499 | /* Stop if not enough space to put next UUID */ | ||
500 | if ((ptr - data) + sizeof(u32) > len) { | ||
501 | uuids_start[1] = EIR_UUID32_SOME; | ||
502 | break; | ||
503 | } | ||
504 | |||
505 | memcpy(ptr, &uuid->uuid[12], sizeof(u32)); | ||
506 | ptr += sizeof(u32); | ||
507 | uuids_start[0] += sizeof(u32); | ||
451 | } | 508 | } |
452 | 509 | ||
453 | val = get_unaligned_le32(&uuid128[12]); | 510 | return ptr; |
454 | if (val > 0xffff) | 511 | } |
455 | return 0; | 512 | |
513 | static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) | ||
514 | { | ||
515 | u8 *ptr = data, *uuids_start = NULL; | ||
516 | struct bt_uuid *uuid; | ||
517 | |||
518 | if (len < 18) | ||
519 | return ptr; | ||
456 | 520 | ||
457 | return (u16) val; | 521 | list_for_each_entry(uuid, &hdev->uuids, list) { |
522 | if (uuid->size != 128) | ||
523 | continue; | ||
524 | |||
525 | if (!uuids_start) { | ||
526 | uuids_start = ptr; | ||
527 | uuids_start[0] = 1; | ||
528 | uuids_start[1] = EIR_UUID128_ALL; | ||
529 | ptr += 2; | ||
530 | } | ||
531 | |||
532 | /* Stop if not enough space to put next UUID */ | ||
533 | if ((ptr - data) + 16 > len) { | ||
534 | uuids_start[1] = EIR_UUID128_SOME; | ||
535 | break; | ||
536 | } | ||
537 | |||
538 | memcpy(ptr, uuid->uuid, 16); | ||
539 | ptr += 16; | ||
540 | uuids_start[0] += 16; | ||
541 | } | ||
542 | |||
543 | return ptr; | ||
458 | } | 544 | } |
459 | 545 | ||
460 | static void create_eir(struct hci_dev *hdev, u8 *data) | 546 | static void create_eir(struct hci_dev *hdev, u8 *data) |
461 | { | 547 | { |
462 | u8 *ptr = data; | 548 | u8 *ptr = data; |
463 | u16 eir_len = 0; | ||
464 | u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)]; | ||
465 | int i, truncated = 0; | ||
466 | struct bt_uuid *uuid; | ||
467 | size_t name_len; | 549 | size_t name_len; |
468 | 550 | ||
469 | name_len = strlen(hdev->dev_name); | 551 | name_len = strlen(hdev->dev_name); |
@@ -481,7 +563,6 @@ static void create_eir(struct hci_dev *hdev, u8 *data) | |||
481 | 563 | ||
482 | memcpy(ptr + 2, hdev->dev_name, name_len); | 564 | memcpy(ptr + 2, hdev->dev_name, name_len); |
483 | 565 | ||
484 | eir_len += (name_len + 2); | ||
485 | ptr += (name_len + 2); | 566 | ptr += (name_len + 2); |
486 | } | 567 | } |
487 | 568 | ||
@@ -490,7 +571,6 @@ static void create_eir(struct hci_dev *hdev, u8 *data) | |||
490 | ptr[1] = EIR_TX_POWER; | 571 | ptr[1] = EIR_TX_POWER; |
491 | ptr[2] = (u8) hdev->inq_tx_power; | 572 | ptr[2] = (u8) hdev->inq_tx_power; |
492 | 573 | ||
493 | eir_len += 3; | ||
494 | ptr += 3; | 574 | ptr += 3; |
495 | } | 575 | } |
496 | 576 | ||
@@ -503,60 +583,12 @@ static void create_eir(struct hci_dev *hdev, u8 *data) | |||
503 | put_unaligned_le16(hdev->devid_product, ptr + 6); | 583 | put_unaligned_le16(hdev->devid_product, ptr + 6); |
504 | put_unaligned_le16(hdev->devid_version, ptr + 8); | 584 | put_unaligned_le16(hdev->devid_version, ptr + 8); |
505 | 585 | ||
506 | eir_len += 10; | ||
507 | ptr += 10; | 586 | ptr += 10; |
508 | } | 587 | } |
509 | 588 | ||
510 | memset(uuid16_list, 0, sizeof(uuid16_list)); | 589 | ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); |
511 | 590 | ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | |
512 | /* Group all UUID16 types */ | 591 | ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); |
513 | list_for_each_entry(uuid, &hdev->uuids, list) { | ||
514 | u16 uuid16; | ||
515 | |||
516 | uuid16 = get_uuid16(uuid->uuid); | ||
517 | if (uuid16 == 0) | ||
518 | return; | ||
519 | |||
520 | if (uuid16 < 0x1100) | ||
521 | continue; | ||
522 | |||
523 | if (uuid16 == PNP_INFO_SVCLASS_ID) | ||
524 | continue; | ||
525 | |||
526 | /* Stop if not enough space to put next UUID */ | ||
527 | if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) { | ||
528 | truncated = 1; | ||
529 | break; | ||
530 | } | ||
531 | |||
532 | /* Check for duplicates */ | ||
533 | for (i = 0; uuid16_list[i] != 0; i++) | ||
534 | if (uuid16_list[i] == uuid16) | ||
535 | break; | ||
536 | |||
537 | if (uuid16_list[i] == 0) { | ||
538 | uuid16_list[i] = uuid16; | ||
539 | eir_len += sizeof(u16); | ||
540 | } | ||
541 | } | ||
542 | |||
543 | if (uuid16_list[0] != 0) { | ||
544 | u8 *length = ptr; | ||
545 | |||
546 | /* EIR Data type */ | ||
547 | ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL; | ||
548 | |||
549 | ptr += 2; | ||
550 | eir_len += 2; | ||
551 | |||
552 | for (i = 0; uuid16_list[i] != 0; i++) { | ||
553 | *ptr++ = (uuid16_list[i] & 0x00ff); | ||
554 | *ptr++ = (uuid16_list[i] & 0xff00) >> 8; | ||
555 | } | ||
556 | |||
557 | /* EIR Data length */ | ||
558 | *length = (i * sizeof(u16)) + 1; | ||
559 | } | ||
560 | } | 592 | } |
561 | 593 | ||
562 | static int update_eir(struct hci_dev *hdev) | 594 | static int update_eir(struct hci_dev *hdev) |
@@ -728,13 +760,9 @@ static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, | |||
728 | void *data), | 760 | void *data), |
729 | void *data) | 761 | void *data) |
730 | { | 762 | { |
731 | struct list_head *p, *n; | 763 | struct pending_cmd *cmd, *tmp; |
732 | |||
733 | list_for_each_safe(p, n, &hdev->mgmt_pending) { | ||
734 | struct pending_cmd *cmd; | ||
735 | |||
736 | cmd = list_entry(p, struct pending_cmd, list); | ||
737 | 764 | ||
765 | list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) { | ||
738 | if (opcode > 0 && cmd->opcode != opcode) | 766 | if (opcode > 0 && cmd->opcode != opcode) |
739 | continue; | 767 | continue; |
740 | 768 | ||
@@ -777,14 +805,19 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, | |||
777 | 805 | ||
778 | BT_DBG("request for %s", hdev->name); | 806 | BT_DBG("request for %s", hdev->name); |
779 | 807 | ||
808 | if (cp->val != 0x00 && cp->val != 0x01) | ||
809 | return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED, | ||
810 | MGMT_STATUS_INVALID_PARAMS); | ||
811 | |||
780 | hci_dev_lock(hdev); | 812 | hci_dev_lock(hdev); |
781 | 813 | ||
782 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { | 814 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { |
783 | cancel_delayed_work(&hdev->power_off); | 815 | cancel_delayed_work(&hdev->power_off); |
784 | 816 | ||
785 | if (cp->val) { | 817 | if (cp->val) { |
786 | err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev); | 818 | mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, |
787 | mgmt_powered(hdev, 1); | 819 | data, len); |
820 | err = mgmt_powered(hdev, 1); | ||
788 | goto failed; | 821 | goto failed; |
789 | } | 822 | } |
790 | } | 823 | } |
@@ -807,9 +840,9 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, | |||
807 | } | 840 | } |
808 | 841 | ||
809 | if (cp->val) | 842 | if (cp->val) |
810 | schedule_work(&hdev->power_on); | 843 | queue_work(hdev->req_workqueue, &hdev->power_on); |
811 | else | 844 | else |
812 | schedule_work(&hdev->power_off.work); | 845 | queue_work(hdev->req_workqueue, &hdev->power_off.work); |
813 | 846 | ||
814 | err = 0; | 847 | err = 0; |
815 | 848 | ||
@@ -872,6 +905,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, | 905 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, |
873 | MGMT_STATUS_NOT_SUPPORTED); | 906 | MGMT_STATUS_NOT_SUPPORTED); |
874 | 907 | ||
908 | if (cp->val != 0x00 && cp->val != 0x01) | ||
909 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | ||
910 | MGMT_STATUS_INVALID_PARAMS); | ||
911 | |||
875 | timeout = __le16_to_cpu(cp->timeout); | 912 | timeout = __le16_to_cpu(cp->timeout); |
876 | if (!cp->val && timeout > 0) | 913 | if (!cp->val && timeout > 0) |
877 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | 914 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, |
@@ -971,6 +1008,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, | 1008 | return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, |
972 | MGMT_STATUS_NOT_SUPPORTED); | 1009 | MGMT_STATUS_NOT_SUPPORTED); |
973 | 1010 | ||
1011 | if (cp->val != 0x00 && cp->val != 0x01) | ||
1012 | return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, | ||
1013 | MGMT_STATUS_INVALID_PARAMS); | ||
1014 | |||
974 | hci_dev_lock(hdev); | 1015 | hci_dev_lock(hdev); |
975 | 1016 | ||
976 | if (!hdev_is_powered(hdev)) { | 1017 | if (!hdev_is_powered(hdev)) { |
@@ -1041,6 +1082,10 @@ static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1041 | 1082 | ||
1042 | BT_DBG("request for %s", hdev->name); | 1083 | BT_DBG("request for %s", hdev->name); |
1043 | 1084 | ||
1085 | if (cp->val != 0x00 && cp->val != 0x01) | ||
1086 | return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE, | ||
1087 | MGMT_STATUS_INVALID_PARAMS); | ||
1088 | |||
1044 | hci_dev_lock(hdev); | 1089 | hci_dev_lock(hdev); |
1045 | 1090 | ||
1046 | if (cp->val) | 1091 | if (cp->val) |
@@ -1073,6 +1118,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, | 1118 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY, |
1074 | MGMT_STATUS_NOT_SUPPORTED); | 1119 | MGMT_STATUS_NOT_SUPPORTED); |
1075 | 1120 | ||
1121 | if (cp->val != 0x00 && cp->val != 0x01) | ||
1122 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY, | ||
1123 | MGMT_STATUS_INVALID_PARAMS); | ||
1124 | |||
1076 | hci_dev_lock(hdev); | 1125 | hci_dev_lock(hdev); |
1077 | 1126 | ||
1078 | if (!hdev_is_powered(hdev)) { | 1127 | if (!hdev_is_powered(hdev)) { |
@@ -1133,13 +1182,15 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1133 | 1182 | ||
1134 | BT_DBG("request for %s", hdev->name); | 1183 | BT_DBG("request for %s", hdev->name); |
1135 | 1184 | ||
1136 | hci_dev_lock(hdev); | 1185 | if (!lmp_ssp_capable(hdev)) |
1186 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, | ||
1187 | MGMT_STATUS_NOT_SUPPORTED); | ||
1137 | 1188 | ||
1138 | if (!lmp_ssp_capable(hdev)) { | 1189 | if (cp->val != 0x00 && cp->val != 0x01) |
1139 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, | 1190 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, |
1140 | MGMT_STATUS_NOT_SUPPORTED); | 1191 | MGMT_STATUS_INVALID_PARAMS); |
1141 | goto failed; | 1192 | |
1142 | } | 1193 | hci_dev_lock(hdev); |
1143 | 1194 | ||
1144 | val = !!cp->val; | 1195 | val = !!cp->val; |
1145 | 1196 | ||
@@ -1199,6 +1250,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, | 1250 | return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, |
1200 | MGMT_STATUS_NOT_SUPPORTED); | 1251 | MGMT_STATUS_NOT_SUPPORTED); |
1201 | 1252 | ||
1253 | if (cp->val != 0x00 && cp->val != 0x01) | ||
1254 | return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, | ||
1255 | MGMT_STATUS_INVALID_PARAMS); | ||
1256 | |||
1202 | if (cp->val) | 1257 | if (cp->val) |
1203 | set_bit(HCI_HS_ENABLED, &hdev->dev_flags); | 1258 | set_bit(HCI_HS_ENABLED, &hdev->dev_flags); |
1204 | else | 1259 | else |
@@ -1217,13 +1272,15 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1217 | 1272 | ||
1218 | BT_DBG("request for %s", hdev->name); | 1273 | BT_DBG("request for %s", hdev->name); |
1219 | 1274 | ||
1220 | hci_dev_lock(hdev); | 1275 | if (!lmp_le_capable(hdev)) |
1276 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LE, | ||
1277 | MGMT_STATUS_NOT_SUPPORTED); | ||
1221 | 1278 | ||
1222 | if (!lmp_le_capable(hdev)) { | 1279 | if (cp->val != 0x00 && cp->val != 0x01) |
1223 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE, | 1280 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LE, |
1224 | MGMT_STATUS_NOT_SUPPORTED); | 1281 | MGMT_STATUS_INVALID_PARAMS); |
1225 | goto unlock; | 1282 | |
1226 | } | 1283 | hci_dev_lock(hdev); |
1227 | 1284 | ||
1228 | val = !!cp->val; | 1285 | val = !!cp->val; |
1229 | enabled = lmp_host_le_capable(hdev); | 1286 | enabled = lmp_host_le_capable(hdev); |
@@ -1275,6 +1332,25 @@ unlock: | |||
1275 | return err; | 1332 | return err; |
1276 | } | 1333 | } |
1277 | 1334 | ||
1335 | static const u8 bluetooth_base_uuid[] = { | ||
1336 | 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, | ||
1337 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
1338 | }; | ||
1339 | |||
1340 | static u8 get_uuid_size(const u8 *uuid) | ||
1341 | { | ||
1342 | u32 val; | ||
1343 | |||
1344 | if (memcmp(uuid, bluetooth_base_uuid, 12)) | ||
1345 | return 128; | ||
1346 | |||
1347 | val = get_unaligned_le32(&uuid[12]); | ||
1348 | if (val > 0xffff) | ||
1349 | return 32; | ||
1350 | |||
1351 | return 16; | ||
1352 | } | ||
1353 | |||
1278 | static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | 1354 | static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) |
1279 | { | 1355 | { |
1280 | struct mgmt_cp_add_uuid *cp = data; | 1356 | struct mgmt_cp_add_uuid *cp = data; |
@@ -1300,8 +1376,9 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1300 | 1376 | ||
1301 | memcpy(uuid->uuid, cp->uuid, 16); | 1377 | memcpy(uuid->uuid, cp->uuid, 16); |
1302 | uuid->svc_hint = cp->svc_hint; | 1378 | uuid->svc_hint = cp->svc_hint; |
1379 | uuid->size = get_uuid_size(cp->uuid); | ||
1303 | 1380 | ||
1304 | list_add(&uuid->list, &hdev->uuids); | 1381 | list_add_tail(&uuid->list, &hdev->uuids); |
1305 | 1382 | ||
1306 | err = update_class(hdev); | 1383 | err = update_class(hdev); |
1307 | if (err < 0) | 1384 | if (err < 0) |
@@ -1332,7 +1409,8 @@ static bool enable_service_cache(struct hci_dev *hdev) | |||
1332 | return false; | 1409 | return false; |
1333 | 1410 | ||
1334 | if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) { | 1411 | if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) { |
1335 | schedule_delayed_work(&hdev->service_cache, CACHE_TIMEOUT); | 1412 | queue_delayed_work(hdev->workqueue, &hdev->service_cache, |
1413 | CACHE_TIMEOUT); | ||
1336 | return true; | 1414 | return true; |
1337 | } | 1415 | } |
1338 | 1416 | ||
@@ -1344,7 +1422,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1344 | { | 1422 | { |
1345 | struct mgmt_cp_remove_uuid *cp = data; | 1423 | struct mgmt_cp_remove_uuid *cp = data; |
1346 | struct pending_cmd *cmd; | 1424 | struct pending_cmd *cmd; |
1347 | struct list_head *p, *n; | 1425 | struct bt_uuid *match, *tmp; |
1348 | u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | 1426 | u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
1349 | int err, found; | 1427 | int err, found; |
1350 | 1428 | ||
@@ -1372,9 +1450,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1372 | 1450 | ||
1373 | found = 0; | 1451 | found = 0; |
1374 | 1452 | ||
1375 | list_for_each_safe(p, n, &hdev->uuids) { | 1453 | list_for_each_entry_safe(match, tmp, &hdev->uuids, list) { |
1376 | struct bt_uuid *match = list_entry(p, struct bt_uuid, list); | ||
1377 | |||
1378 | if (memcmp(match->uuid, cp->uuid, 16) != 0) | 1454 | if (memcmp(match->uuid, cp->uuid, 16) != 0) |
1379 | continue; | 1455 | continue; |
1380 | 1456 | ||
@@ -1422,13 +1498,19 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1422 | 1498 | ||
1423 | BT_DBG("request for %s", hdev->name); | 1499 | BT_DBG("request for %s", hdev->name); |
1424 | 1500 | ||
1425 | hci_dev_lock(hdev); | 1501 | if (!lmp_bredr_capable(hdev)) |
1502 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | ||
1503 | MGMT_STATUS_NOT_SUPPORTED); | ||
1426 | 1504 | ||
1427 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | 1505 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) |
1428 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | 1506 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, |
1429 | MGMT_STATUS_BUSY); | 1507 | MGMT_STATUS_BUSY); |
1430 | goto unlock; | 1508 | |
1431 | } | 1509 | if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) |
1510 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | ||
1511 | MGMT_STATUS_INVALID_PARAMS); | ||
1512 | |||
1513 | hci_dev_lock(hdev); | ||
1432 | 1514 | ||
1433 | hdev->major_class = cp->major; | 1515 | hdev->major_class = cp->major; |
1434 | hdev->minor_class = cp->minor; | 1516 | hdev->minor_class = cp->minor; |
@@ -1483,9 +1565,21 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1483 | MGMT_STATUS_INVALID_PARAMS); | 1565 | MGMT_STATUS_INVALID_PARAMS); |
1484 | } | 1566 | } |
1485 | 1567 | ||
1568 | if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01) | ||
1569 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, | ||
1570 | MGMT_STATUS_INVALID_PARAMS); | ||
1571 | |||
1486 | BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys, | 1572 | BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys, |
1487 | key_count); | 1573 | key_count); |
1488 | 1574 | ||
1575 | for (i = 0; i < key_count; i++) { | ||
1576 | struct mgmt_link_key_info *key = &cp->keys[i]; | ||
1577 | |||
1578 | if (key->addr.type != BDADDR_BREDR) | ||
1579 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, | ||
1580 | MGMT_STATUS_INVALID_PARAMS); | ||
1581 | } | ||
1582 | |||
1489 | hci_dev_lock(hdev); | 1583 | hci_dev_lock(hdev); |
1490 | 1584 | ||
1491 | hci_link_keys_clear(hdev); | 1585 | hci_link_keys_clear(hdev); |
@@ -1533,12 +1627,22 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1533 | struct hci_conn *conn; | 1627 | struct hci_conn *conn; |
1534 | int err; | 1628 | int err; |
1535 | 1629 | ||
1536 | hci_dev_lock(hdev); | ||
1537 | |||
1538 | memset(&rp, 0, sizeof(rp)); | 1630 | memset(&rp, 0, sizeof(rp)); |
1539 | bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); | 1631 | bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); |
1540 | rp.addr.type = cp->addr.type; | 1632 | rp.addr.type = cp->addr.type; |
1541 | 1633 | ||
1634 | if (!bdaddr_type_is_valid(cp->addr.type)) | ||
1635 | return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, | ||
1636 | MGMT_STATUS_INVALID_PARAMS, | ||
1637 | &rp, sizeof(rp)); | ||
1638 | |||
1639 | if (cp->disconnect != 0x00 && cp->disconnect != 0x01) | ||
1640 | return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, | ||
1641 | MGMT_STATUS_INVALID_PARAMS, | ||
1642 | &rp, sizeof(rp)); | ||
1643 | |||
1644 | hci_dev_lock(hdev); | ||
1645 | |||
1542 | if (!hdev_is_powered(hdev)) { | 1646 | if (!hdev_is_powered(hdev)) { |
1543 | err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, | 1647 | err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, |
1544 | MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); | 1648 | MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); |
@@ -1596,6 +1700,7 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1596 | u16 len) | 1700 | u16 len) |
1597 | { | 1701 | { |
1598 | struct mgmt_cp_disconnect *cp = data; | 1702 | struct mgmt_cp_disconnect *cp = data; |
1703 | struct mgmt_rp_disconnect rp; | ||
1599 | struct hci_cp_disconnect dc; | 1704 | struct hci_cp_disconnect dc; |
1600 | struct pending_cmd *cmd; | 1705 | struct pending_cmd *cmd; |
1601 | struct hci_conn *conn; | 1706 | struct hci_conn *conn; |
@@ -1603,17 +1708,26 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1603 | 1708 | ||
1604 | BT_DBG(""); | 1709 | BT_DBG(""); |
1605 | 1710 | ||
1711 | memset(&rp, 0, sizeof(rp)); | ||
1712 | bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); | ||
1713 | rp.addr.type = cp->addr.type; | ||
1714 | |||
1715 | if (!bdaddr_type_is_valid(cp->addr.type)) | ||
1716 | return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, | ||
1717 | MGMT_STATUS_INVALID_PARAMS, | ||
1718 | &rp, sizeof(rp)); | ||
1719 | |||
1606 | hci_dev_lock(hdev); | 1720 | hci_dev_lock(hdev); |
1607 | 1721 | ||
1608 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1722 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1609 | err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT, | 1723 | err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, |
1610 | MGMT_STATUS_NOT_POWERED); | 1724 | MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); |
1611 | goto failed; | 1725 | goto failed; |
1612 | } | 1726 | } |
1613 | 1727 | ||
1614 | if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) { | 1728 | if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) { |
1615 | err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT, | 1729 | err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, |
1616 | MGMT_STATUS_BUSY); | 1730 | MGMT_STATUS_BUSY, &rp, sizeof(rp)); |
1617 | goto failed; | 1731 | goto failed; |
1618 | } | 1732 | } |
1619 | 1733 | ||
@@ -1624,8 +1738,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); | 1738 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); |
1625 | 1739 | ||
1626 | if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) { | 1740 | if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) { |
1627 | err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT, | 1741 | err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT, |
1628 | MGMT_STATUS_NOT_CONNECTED); | 1742 | MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp)); |
1629 | goto failed; | 1743 | goto failed; |
1630 | } | 1744 | } |
1631 | 1745 | ||
@@ -1903,11 +2017,20 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1903 | 2017 | ||
1904 | BT_DBG(""); | 2018 | BT_DBG(""); |
1905 | 2019 | ||
2020 | memset(&rp, 0, sizeof(rp)); | ||
2021 | bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); | ||
2022 | rp.addr.type = cp->addr.type; | ||
2023 | |||
2024 | if (!bdaddr_type_is_valid(cp->addr.type)) | ||
2025 | return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE, | ||
2026 | MGMT_STATUS_INVALID_PARAMS, | ||
2027 | &rp, sizeof(rp)); | ||
2028 | |||
1906 | hci_dev_lock(hdev); | 2029 | hci_dev_lock(hdev); |
1907 | 2030 | ||
1908 | if (!hdev_is_powered(hdev)) { | 2031 | if (!hdev_is_powered(hdev)) { |
1909 | err = cmd_status(sk, hdev->id, MGMT_OP_PAIR_DEVICE, | 2032 | err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE, |
1910 | MGMT_STATUS_NOT_POWERED); | 2033 | MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); |
1911 | goto unlock; | 2034 | goto unlock; |
1912 | } | 2035 | } |
1913 | 2036 | ||
@@ -1924,10 +2047,6 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1924 | conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, | 2047 | conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, |
1925 | cp->addr.type, sec_level, auth_type); | 2048 | cp->addr.type, sec_level, auth_type); |
1926 | 2049 | ||
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)) { | 2050 | if (IS_ERR(conn)) { |
1932 | int status; | 2051 | int status; |
1933 | 2052 | ||
@@ -2254,24 +2373,16 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, | |||
2254 | 2373 | ||
2255 | hci_dev_lock(hdev); | 2374 | hci_dev_lock(hdev); |
2256 | 2375 | ||
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, | 2376 | err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr, cp->hash, |
2265 | cp->randomizer); | 2377 | cp->randomizer); |
2266 | if (err < 0) | 2378 | if (err < 0) |
2267 | status = MGMT_STATUS_FAILED; | 2379 | status = MGMT_STATUS_FAILED; |
2268 | else | 2380 | else |
2269 | status = 0; | 2381 | status = MGMT_STATUS_SUCCESS; |
2270 | 2382 | ||
2271 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, status, | 2383 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, status, |
2272 | &cp->addr, sizeof(cp->addr)); | 2384 | &cp->addr, sizeof(cp->addr)); |
2273 | 2385 | ||
2274 | unlock: | ||
2275 | hci_dev_unlock(hdev); | 2386 | hci_dev_unlock(hdev); |
2276 | return err; | 2387 | return err; |
2277 | } | 2388 | } |
@@ -2287,24 +2398,15 @@ static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev, | |||
2287 | 2398 | ||
2288 | hci_dev_lock(hdev); | 2399 | hci_dev_lock(hdev); |
2289 | 2400 | ||
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); | 2401 | err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr); |
2299 | if (err < 0) | 2402 | if (err < 0) |
2300 | status = MGMT_STATUS_INVALID_PARAMS; | 2403 | status = MGMT_STATUS_INVALID_PARAMS; |
2301 | else | 2404 | else |
2302 | status = 0; | 2405 | status = MGMT_STATUS_SUCCESS; |
2303 | 2406 | ||
2304 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA, | 2407 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA, |
2305 | status, &cp->addr, sizeof(cp->addr)); | 2408 | status, &cp->addr, sizeof(cp->addr)); |
2306 | 2409 | ||
2307 | unlock: | ||
2308 | hci_dev_unlock(hdev); | 2410 | hci_dev_unlock(hdev); |
2309 | return err; | 2411 | return err; |
2310 | } | 2412 | } |
@@ -2365,31 +2467,45 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
2365 | 2467 | ||
2366 | switch (hdev->discovery.type) { | 2468 | switch (hdev->discovery.type) { |
2367 | case DISCOV_TYPE_BREDR: | 2469 | case DISCOV_TYPE_BREDR: |
2368 | if (lmp_bredr_capable(hdev)) | 2470 | if (!lmp_bredr_capable(hdev)) { |
2369 | err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR); | 2471 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
2370 | else | 2472 | MGMT_STATUS_NOT_SUPPORTED); |
2371 | err = -ENOTSUPP; | 2473 | mgmt_pending_remove(cmd); |
2474 | goto failed; | ||
2475 | } | ||
2476 | |||
2477 | err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR); | ||
2372 | break; | 2478 | break; |
2373 | 2479 | ||
2374 | case DISCOV_TYPE_LE: | 2480 | case DISCOV_TYPE_LE: |
2375 | if (lmp_host_le_capable(hdev)) | 2481 | if (!lmp_host_le_capable(hdev)) { |
2376 | err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT, | 2482 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
2377 | LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY); | 2483 | MGMT_STATUS_NOT_SUPPORTED); |
2378 | else | 2484 | mgmt_pending_remove(cmd); |
2379 | err = -ENOTSUPP; | 2485 | goto failed; |
2486 | } | ||
2487 | |||
2488 | err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT, | ||
2489 | LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY); | ||
2380 | break; | 2490 | break; |
2381 | 2491 | ||
2382 | case DISCOV_TYPE_INTERLEAVED: | 2492 | case DISCOV_TYPE_INTERLEAVED: |
2383 | if (lmp_host_le_capable(hdev) && lmp_bredr_capable(hdev)) | 2493 | if (!lmp_host_le_capable(hdev) || !lmp_bredr_capable(hdev)) { |
2384 | err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT, | 2494 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
2385 | LE_SCAN_WIN, | 2495 | MGMT_STATUS_NOT_SUPPORTED); |
2386 | LE_SCAN_TIMEOUT_BREDR_LE); | 2496 | mgmt_pending_remove(cmd); |
2387 | else | 2497 | goto failed; |
2388 | err = -ENOTSUPP; | 2498 | } |
2499 | |||
2500 | err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT, LE_SCAN_WIN, | ||
2501 | LE_SCAN_TIMEOUT_BREDR_LE); | ||
2389 | break; | 2502 | break; |
2390 | 2503 | ||
2391 | default: | 2504 | default: |
2392 | err = -EINVAL; | 2505 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
2506 | MGMT_STATUS_INVALID_PARAMS); | ||
2507 | mgmt_pending_remove(cmd); | ||
2508 | goto failed; | ||
2393 | } | 2509 | } |
2394 | 2510 | ||
2395 | if (err < 0) | 2511 | if (err < 0) |
@@ -2510,7 +2626,8 @@ static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2510 | hci_inquiry_cache_update_resolve(hdev, e); | 2626 | hci_inquiry_cache_update_resolve(hdev, e); |
2511 | } | 2627 | } |
2512 | 2628 | ||
2513 | err = 0; | 2629 | err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr, |
2630 | sizeof(cp->addr)); | ||
2514 | 2631 | ||
2515 | failed: | 2632 | failed: |
2516 | hci_dev_unlock(hdev); | 2633 | hci_dev_unlock(hdev); |
@@ -2526,13 +2643,18 @@ static int block_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2526 | 2643 | ||
2527 | BT_DBG("%s", hdev->name); | 2644 | BT_DBG("%s", hdev->name); |
2528 | 2645 | ||
2646 | if (!bdaddr_type_is_valid(cp->addr.type)) | ||
2647 | return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, | ||
2648 | MGMT_STATUS_INVALID_PARAMS, | ||
2649 | &cp->addr, sizeof(cp->addr)); | ||
2650 | |||
2529 | hci_dev_lock(hdev); | 2651 | hci_dev_lock(hdev); |
2530 | 2652 | ||
2531 | err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type); | 2653 | err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type); |
2532 | if (err < 0) | 2654 | if (err < 0) |
2533 | status = MGMT_STATUS_FAILED; | 2655 | status = MGMT_STATUS_FAILED; |
2534 | else | 2656 | else |
2535 | status = 0; | 2657 | status = MGMT_STATUS_SUCCESS; |
2536 | 2658 | ||
2537 | err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status, | 2659 | err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status, |
2538 | &cp->addr, sizeof(cp->addr)); | 2660 | &cp->addr, sizeof(cp->addr)); |
@@ -2551,13 +2673,18 @@ static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2551 | 2673 | ||
2552 | BT_DBG("%s", hdev->name); | 2674 | BT_DBG("%s", hdev->name); |
2553 | 2675 | ||
2676 | if (!bdaddr_type_is_valid(cp->addr.type)) | ||
2677 | return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, | ||
2678 | MGMT_STATUS_INVALID_PARAMS, | ||
2679 | &cp->addr, sizeof(cp->addr)); | ||
2680 | |||
2554 | hci_dev_lock(hdev); | 2681 | hci_dev_lock(hdev); |
2555 | 2682 | ||
2556 | err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type); | 2683 | err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type); |
2557 | if (err < 0) | 2684 | if (err < 0) |
2558 | status = MGMT_STATUS_INVALID_PARAMS; | 2685 | status = MGMT_STATUS_INVALID_PARAMS; |
2559 | else | 2686 | else |
2560 | status = 0; | 2687 | status = MGMT_STATUS_SUCCESS; |
2561 | 2688 | ||
2562 | err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status, | 2689 | err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status, |
2563 | &cp->addr, sizeof(cp->addr)); | 2690 | &cp->addr, sizeof(cp->addr)); |
@@ -2612,6 +2739,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, | 2739 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
2613 | MGMT_STATUS_NOT_SUPPORTED); | 2740 | MGMT_STATUS_NOT_SUPPORTED); |
2614 | 2741 | ||
2742 | if (cp->val != 0x00 && cp->val != 0x01) | ||
2743 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | ||
2744 | MGMT_STATUS_INVALID_PARAMS); | ||
2745 | |||
2615 | if (!hdev_is_powered(hdev)) | 2746 | if (!hdev_is_powered(hdev)) |
2616 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | 2747 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
2617 | MGMT_STATUS_NOT_POWERED); | 2748 | MGMT_STATUS_NOT_POWERED); |
@@ -2659,12 +2790,23 @@ done: | |||
2659 | return err; | 2790 | return err; |
2660 | } | 2791 | } |
2661 | 2792 | ||
2793 | static bool ltk_is_valid(struct mgmt_ltk_info *key) | ||
2794 | { | ||
2795 | if (key->authenticated != 0x00 && key->authenticated != 0x01) | ||
2796 | return false; | ||
2797 | if (key->master != 0x00 && key->master != 0x01) | ||
2798 | return false; | ||
2799 | if (!bdaddr_type_is_le(key->addr.type)) | ||
2800 | return false; | ||
2801 | return true; | ||
2802 | } | ||
2803 | |||
2662 | static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | 2804 | static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, |
2663 | void *cp_data, u16 len) | 2805 | void *cp_data, u16 len) |
2664 | { | 2806 | { |
2665 | struct mgmt_cp_load_long_term_keys *cp = cp_data; | 2807 | struct mgmt_cp_load_long_term_keys *cp = cp_data; |
2666 | u16 key_count, expected_len; | 2808 | u16 key_count, expected_len; |
2667 | int i; | 2809 | int i, err; |
2668 | 2810 | ||
2669 | key_count = __le16_to_cpu(cp->key_count); | 2811 | key_count = __le16_to_cpu(cp->key_count); |
2670 | 2812 | ||
@@ -2674,11 +2816,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", | 2816 | BT_ERR("load_keys: expected %u bytes, got %u bytes", |
2675 | len, expected_len); | 2817 | len, expected_len); |
2676 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, | 2818 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, |
2677 | EINVAL); | 2819 | MGMT_STATUS_INVALID_PARAMS); |
2678 | } | 2820 | } |
2679 | 2821 | ||
2680 | BT_DBG("%s key_count %u", hdev->name, key_count); | 2822 | BT_DBG("%s key_count %u", hdev->name, key_count); |
2681 | 2823 | ||
2824 | for (i = 0; i < key_count; i++) { | ||
2825 | struct mgmt_ltk_info *key = &cp->keys[i]; | ||
2826 | |||
2827 | if (!ltk_is_valid(key)) | ||
2828 | return cmd_status(sk, hdev->id, | ||
2829 | MGMT_OP_LOAD_LONG_TERM_KEYS, | ||
2830 | MGMT_STATUS_INVALID_PARAMS); | ||
2831 | } | ||
2832 | |||
2682 | hci_dev_lock(hdev); | 2833 | hci_dev_lock(hdev); |
2683 | 2834 | ||
2684 | hci_smp_ltks_clear(hdev); | 2835 | hci_smp_ltks_clear(hdev); |
@@ -2698,9 +2849,12 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | |||
2698 | key->enc_size, key->ediv, key->rand); | 2849 | key->enc_size, key->ediv, key->rand); |
2699 | } | 2850 | } |
2700 | 2851 | ||
2852 | err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0, | ||
2853 | NULL, 0); | ||
2854 | |||
2701 | hci_dev_unlock(hdev); | 2855 | hci_dev_unlock(hdev); |
2702 | 2856 | ||
2703 | return 0; | 2857 | return err; |
2704 | } | 2858 | } |
2705 | 2859 | ||
2706 | static const struct mgmt_handler { | 2860 | static const struct mgmt_handler { |
@@ -2915,6 +3069,8 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) | |||
2915 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | 3069 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); |
2916 | 3070 | ||
2917 | if (powered) { | 3071 | if (powered) { |
3072 | u8 link_sec; | ||
3073 | |||
2918 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && | 3074 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && |
2919 | !lmp_host_ssp_capable(hdev)) { | 3075 | !lmp_host_ssp_capable(hdev)) { |
2920 | u8 ssp = 1; | 3076 | u8 ssp = 1; |
@@ -2938,6 +3094,11 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) | |||
2938 | sizeof(cp), &cp); | 3094 | sizeof(cp), &cp); |
2939 | } | 3095 | } |
2940 | 3096 | ||
3097 | link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); | ||
3098 | if (link_sec != test_bit(HCI_AUTH, &hdev->flags)) | ||
3099 | hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, | ||
3100 | sizeof(link_sec), &link_sec); | ||
3101 | |||
2941 | if (lmp_bredr_capable(hdev)) { | 3102 | if (lmp_bredr_capable(hdev)) { |
2942 | set_bredr_scan(hdev); | 3103 | set_bredr_scan(hdev); |
2943 | update_class(hdev); | 3104 | update_class(hdev); |
@@ -2946,7 +3107,13 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) | |||
2946 | } | 3107 | } |
2947 | } else { | 3108 | } else { |
2948 | u8 status = MGMT_STATUS_NOT_POWERED; | 3109 | u8 status = MGMT_STATUS_NOT_POWERED; |
3110 | u8 zero_cod[] = { 0, 0, 0 }; | ||
3111 | |||
2949 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | 3112 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); |
3113 | |||
3114 | if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) | ||
3115 | mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, | ||
3116 | zero_cod, sizeof(zero_cod), NULL); | ||
2950 | } | 3117 | } |
2951 | 3118 | ||
2952 | err = new_settings(hdev, match.sk); | 3119 | err = new_settings(hdev, match.sk); |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 57f250c20e39..b5178d62064e 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -900,8 +900,6 @@ static void sco_conn_ready(struct sco_conn *conn) | |||
900 | 900 | ||
901 | BT_DBG("conn %p", conn); | 901 | BT_DBG("conn %p", conn); |
902 | 902 | ||
903 | sco_conn_lock(conn); | ||
904 | |||
905 | if (sk) { | 903 | if (sk) { |
906 | sco_sock_clear_timer(sk); | 904 | sco_sock_clear_timer(sk); |
907 | bh_lock_sock(sk); | 905 | bh_lock_sock(sk); |
@@ -909,9 +907,13 @@ static void sco_conn_ready(struct sco_conn *conn) | |||
909 | sk->sk_state_change(sk); | 907 | sk->sk_state_change(sk); |
910 | bh_unlock_sock(sk); | 908 | bh_unlock_sock(sk); |
911 | } else { | 909 | } else { |
910 | sco_conn_lock(conn); | ||
911 | |||
912 | parent = sco_get_sock_listen(conn->src); | 912 | parent = sco_get_sock_listen(conn->src); |
913 | if (!parent) | 913 | if (!parent) { |
914 | goto done; | 914 | sco_conn_unlock(conn); |
915 | return; | ||
916 | } | ||
915 | 917 | ||
916 | bh_lock_sock(parent); | 918 | bh_lock_sock(parent); |
917 | 919 | ||
@@ -919,7 +921,8 @@ static void sco_conn_ready(struct sco_conn *conn) | |||
919 | BTPROTO_SCO, GFP_ATOMIC); | 921 | BTPROTO_SCO, GFP_ATOMIC); |
920 | if (!sk) { | 922 | if (!sk) { |
921 | bh_unlock_sock(parent); | 923 | bh_unlock_sock(parent); |
922 | goto done; | 924 | sco_conn_unlock(conn); |
925 | return; | ||
923 | } | 926 | } |
924 | 927 | ||
925 | sco_sock_init(sk, parent); | 928 | sco_sock_init(sk, parent); |
@@ -939,10 +942,9 @@ static void sco_conn_ready(struct sco_conn *conn) | |||
939 | parent->sk_data_ready(parent, 1); | 942 | parent->sk_data_ready(parent, 1); |
940 | 943 | ||
941 | bh_unlock_sock(parent); | 944 | bh_unlock_sock(parent); |
942 | } | ||
943 | 945 | ||
944 | done: | 946 | sco_conn_unlock(conn); |
945 | sco_conn_unlock(conn); | 947 | } |
946 | } | 948 | } |
947 | 949 | ||
948 | /* ----- SCO interface with lower layer (HCI) ----- */ | 950 | /* ----- SCO interface with lower layer (HCI) ----- */ |