diff options
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r-- | net/bluetooth/mgmt.c | 100 |
1 files changed, 68 insertions, 32 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 158a87bb0c0..142764aec2a 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -222,7 +222,7 @@ static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) | |||
222 | 222 | ||
223 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 223 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
224 | 224 | ||
225 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS); | 225 | hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_STATUS); |
226 | hdr->index = cpu_to_le16(index); | 226 | hdr->index = cpu_to_le16(index); |
227 | hdr->len = cpu_to_le16(sizeof(*ev)); | 227 | hdr->len = cpu_to_le16(sizeof(*ev)); |
228 | 228 | ||
@@ -253,7 +253,7 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status, | |||
253 | 253 | ||
254 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 254 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
255 | 255 | ||
256 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); | 256 | hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_COMPLETE); |
257 | hdr->index = cpu_to_le16(index); | 257 | hdr->index = cpu_to_le16(index); |
258 | hdr->len = cpu_to_le16(sizeof(*ev) + rp_len); | 258 | hdr->len = cpu_to_le16(sizeof(*ev) + rp_len); |
259 | 259 | ||
@@ -377,15 +377,15 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
377 | u32 settings = 0; | 377 | u32 settings = 0; |
378 | 378 | ||
379 | settings |= MGMT_SETTING_POWERED; | 379 | settings |= MGMT_SETTING_POWERED; |
380 | settings |= MGMT_SETTING_CONNECTABLE; | ||
381 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | ||
382 | settings |= MGMT_SETTING_DISCOVERABLE; | ||
383 | settings |= MGMT_SETTING_PAIRABLE; | 380 | settings |= MGMT_SETTING_PAIRABLE; |
384 | 381 | ||
385 | if (lmp_ssp_capable(hdev)) | 382 | if (lmp_ssp_capable(hdev)) |
386 | settings |= MGMT_SETTING_SSP; | 383 | settings |= MGMT_SETTING_SSP; |
387 | 384 | ||
388 | if (lmp_bredr_capable(hdev)) { | 385 | if (lmp_bredr_capable(hdev)) { |
386 | settings |= MGMT_SETTING_CONNECTABLE; | ||
387 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | ||
388 | settings |= MGMT_SETTING_DISCOVERABLE; | ||
389 | settings |= MGMT_SETTING_BREDR; | 389 | settings |= MGMT_SETTING_BREDR; |
390 | settings |= MGMT_SETTING_LINK_SECURITY; | 390 | settings |= MGMT_SETTING_LINK_SECURITY; |
391 | } | 391 | } |
@@ -485,7 +485,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data) | |||
485 | ptr += (name_len + 2); | 485 | ptr += (name_len + 2); |
486 | } | 486 | } |
487 | 487 | ||
488 | if (hdev->inq_tx_power) { | 488 | if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) { |
489 | ptr[0] = 2; | 489 | ptr[0] = 2; |
490 | ptr[1] = EIR_TX_POWER; | 490 | ptr[1] = EIR_TX_POWER; |
491 | ptr[2] = (u8) hdev->inq_tx_power; | 491 | ptr[2] = (u8) hdev->inq_tx_power; |
@@ -566,7 +566,7 @@ static int update_eir(struct hci_dev *hdev) | |||
566 | if (!hdev_is_powered(hdev)) | 566 | if (!hdev_is_powered(hdev)) |
567 | return 0; | 567 | return 0; |
568 | 568 | ||
569 | if (!(hdev->features[6] & LMP_EXT_INQ)) | 569 | if (!lmp_ext_inq_capable(hdev)) |
570 | return 0; | 570 | return 0; |
571 | 571 | ||
572 | if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) | 572 | if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) |
@@ -833,7 +833,7 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len, | |||
833 | if (hdev) | 833 | if (hdev) |
834 | hdr->index = cpu_to_le16(hdev->id); | 834 | hdr->index = cpu_to_le16(hdev->id); |
835 | else | 835 | else |
836 | hdr->index = cpu_to_le16(MGMT_INDEX_NONE); | 836 | hdr->index = __constant_cpu_to_le16(MGMT_INDEX_NONE); |
837 | hdr->len = cpu_to_le16(data_len); | 837 | hdr->len = cpu_to_le16(data_len); |
838 | 838 | ||
839 | if (data) | 839 | if (data) |
@@ -868,6 +868,10 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
868 | 868 | ||
869 | BT_DBG("request for %s", hdev->name); | 869 | BT_DBG("request for %s", hdev->name); |
870 | 870 | ||
871 | if (!lmp_bredr_capable(hdev)) | ||
872 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | ||
873 | MGMT_STATUS_NOT_SUPPORTED); | ||
874 | |||
871 | timeout = __le16_to_cpu(cp->timeout); | 875 | timeout = __le16_to_cpu(cp->timeout); |
872 | if (!cp->val && timeout > 0) | 876 | if (!cp->val && timeout > 0) |
873 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, | 877 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, |
@@ -963,6 +967,10 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
963 | 967 | ||
964 | BT_DBG("request for %s", hdev->name); | 968 | BT_DBG("request for %s", hdev->name); |
965 | 969 | ||
970 | if (!lmp_bredr_capable(hdev)) | ||
971 | return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, | ||
972 | MGMT_STATUS_NOT_SUPPORTED); | ||
973 | |||
966 | hci_dev_lock(hdev); | 974 | hci_dev_lock(hdev); |
967 | 975 | ||
968 | if (!hdev_is_powered(hdev)) { | 976 | if (!hdev_is_powered(hdev)) { |
@@ -1061,6 +1069,10 @@ static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1061 | 1069 | ||
1062 | BT_DBG("request for %s", hdev->name); | 1070 | BT_DBG("request for %s", hdev->name); |
1063 | 1071 | ||
1072 | if (!lmp_bredr_capable(hdev)) | ||
1073 | return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY, | ||
1074 | MGMT_STATUS_NOT_SUPPORTED); | ||
1075 | |||
1064 | hci_dev_lock(hdev); | 1076 | hci_dev_lock(hdev); |
1065 | 1077 | ||
1066 | if (!hdev_is_powered(hdev)) { | 1078 | if (!hdev_is_powered(hdev)) { |
@@ -1214,7 +1226,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1214 | } | 1226 | } |
1215 | 1227 | ||
1216 | val = !!cp->val; | 1228 | val = !!cp->val; |
1217 | enabled = !!(hdev->host_features[0] & LMP_HOST_LE); | 1229 | enabled = !!lmp_host_le_capable(hdev); |
1218 | 1230 | ||
1219 | if (!hdev_is_powered(hdev) || val == enabled) { | 1231 | if (!hdev_is_powered(hdev) || val == enabled) { |
1220 | bool changed = false; | 1232 | bool changed = false; |
@@ -1250,7 +1262,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1250 | 1262 | ||
1251 | if (val) { | 1263 | if (val) { |
1252 | hci_cp.le = val; | 1264 | hci_cp.le = val; |
1253 | hci_cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); | 1265 | hci_cp.simul = !!lmp_le_br_capable(hdev); |
1254 | } | 1266 | } |
1255 | 1267 | ||
1256 | err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), | 1268 | err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), |
@@ -2596,6 +2608,10 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, | |||
2596 | 2608 | ||
2597 | BT_DBG("%s", hdev->name); | 2609 | BT_DBG("%s", hdev->name); |
2598 | 2610 | ||
2611 | if (!lmp_bredr_capable(hdev)) | ||
2612 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | ||
2613 | MGMT_STATUS_NOT_SUPPORTED); | ||
2614 | |||
2599 | if (!hdev_is_powered(hdev)) | 2615 | if (!hdev_is_powered(hdev)) |
2600 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | 2616 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
2601 | MGMT_STATUS_NOT_POWERED); | 2617 | MGMT_STATUS_NOT_POWERED); |
@@ -2873,6 +2889,21 @@ static void settings_rsp(struct pending_cmd *cmd, void *data) | |||
2873 | mgmt_pending_free(cmd); | 2889 | mgmt_pending_free(cmd); |
2874 | } | 2890 | } |
2875 | 2891 | ||
2892 | static int set_bredr_scan(struct hci_dev *hdev) | ||
2893 | { | ||
2894 | u8 scan = 0; | ||
2895 | |||
2896 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | ||
2897 | scan |= SCAN_PAGE; | ||
2898 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | ||
2899 | scan |= SCAN_INQUIRY; | ||
2900 | |||
2901 | if (!scan) | ||
2902 | return 0; | ||
2903 | |||
2904 | return hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
2905 | } | ||
2906 | |||
2876 | int mgmt_powered(struct hci_dev *hdev, u8 powered) | 2907 | int mgmt_powered(struct hci_dev *hdev, u8 powered) |
2877 | { | 2908 | { |
2878 | struct cmd_lookup match = { NULL, hdev }; | 2909 | struct cmd_lookup match = { NULL, hdev }; |
@@ -2884,17 +2915,8 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) | |||
2884 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | 2915 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); |
2885 | 2916 | ||
2886 | if (powered) { | 2917 | if (powered) { |
2887 | u8 scan = 0; | 2918 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && |
2888 | 2919 | !lmp_host_ssp_capable(hdev)) { | |
2889 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | ||
2890 | scan |= SCAN_PAGE; | ||
2891 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | ||
2892 | scan |= SCAN_INQUIRY; | ||
2893 | |||
2894 | if (scan) | ||
2895 | hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
2896 | |||
2897 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { | ||
2898 | u8 ssp = 1; | 2920 | u8 ssp = 1; |
2899 | 2921 | ||
2900 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp); | 2922 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp); |
@@ -2904,15 +2926,24 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) | |||
2904 | struct hci_cp_write_le_host_supported cp; | 2926 | struct hci_cp_write_le_host_supported cp; |
2905 | 2927 | ||
2906 | cp.le = 1; | 2928 | cp.le = 1; |
2907 | cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); | 2929 | cp.simul = !!lmp_le_br_capable(hdev); |
2908 | 2930 | ||
2909 | hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, | 2931 | /* Check first if we already have the right |
2910 | sizeof(cp), &cp); | 2932 | * host state (host features set) |
2933 | */ | ||
2934 | if (cp.le != !!lmp_host_le_capable(hdev) || | ||
2935 | cp.simul != !!lmp_host_le_br_capable(hdev)) | ||
2936 | hci_send_cmd(hdev, | ||
2937 | HCI_OP_WRITE_LE_HOST_SUPPORTED, | ||
2938 | sizeof(cp), &cp); | ||
2911 | } | 2939 | } |
2912 | 2940 | ||
2913 | update_class(hdev); | 2941 | if (lmp_bredr_capable(hdev)) { |
2914 | update_name(hdev, hdev->dev_name); | 2942 | set_bredr_scan(hdev); |
2915 | update_eir(hdev); | 2943 | update_class(hdev); |
2944 | update_name(hdev, hdev->dev_name); | ||
2945 | update_eir(hdev); | ||
2946 | } | ||
2916 | } else { | 2947 | } else { |
2917 | u8 status = MGMT_STATUS_NOT_POWERED; | 2948 | u8 status = MGMT_STATUS_NOT_POWERED; |
2918 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | 2949 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); |
@@ -3361,7 +3392,7 @@ static int clear_eir(struct hci_dev *hdev) | |||
3361 | { | 3392 | { |
3362 | struct hci_cp_write_eir cp; | 3393 | struct hci_cp_write_eir cp; |
3363 | 3394 | ||
3364 | if (!(hdev->features[6] & LMP_EXT_INQ)) | 3395 | if (!lmp_ext_inq_capable(hdev)) |
3365 | return 0; | 3396 | return 0; |
3366 | 3397 | ||
3367 | memset(hdev->eir, 0, sizeof(hdev->eir)); | 3398 | memset(hdev->eir, 0, sizeof(hdev->eir)); |
@@ -3493,7 +3524,12 @@ send_event: | |||
3493 | err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, | 3524 | err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, |
3494 | sizeof(ev), cmd ? cmd->sk : NULL); | 3525 | sizeof(ev), cmd ? cmd->sk : NULL); |
3495 | 3526 | ||
3496 | update_eir(hdev); | 3527 | /* EIR is taken care of separately when powering on the |
3528 | * adapter so only update them here if this is a name change | ||
3529 | * unrelated to power on. | ||
3530 | */ | ||
3531 | if (!test_bit(HCI_INIT, &hdev->flags)) | ||
3532 | update_eir(hdev); | ||
3497 | 3533 | ||
3498 | failed: | 3534 | failed: |
3499 | if (cmd) | 3535 | if (cmd) |
@@ -3588,9 +3624,9 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
3588 | ev->addr.type = link_to_bdaddr(link_type, addr_type); | 3624 | ev->addr.type = link_to_bdaddr(link_type, addr_type); |
3589 | ev->rssi = rssi; | 3625 | ev->rssi = rssi; |
3590 | if (cfm_name) | 3626 | if (cfm_name) |
3591 | ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME); | 3627 | ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME); |
3592 | if (!ssp) | 3628 | if (!ssp) |
3593 | ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING); | 3629 | ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING); |
3594 | 3630 | ||
3595 | if (eir_len > 0) | 3631 | if (eir_len > 0) |
3596 | memcpy(ev->eir, eir, eir_len); | 3632 | memcpy(ev->eir, eir, eir_len); |