mgmt.c (5c49bcce5c124406920843af65574104aaaa3309) mgmt.c (cbbdfa6f331980c6786b4ca5df53c37b90df3246)
1/*
2 BlueZ - Bluetooth protocol stack for Linux
3
4 Copyright (C) 2010 Nokia Corporation
5 Copyright (C) 2011-2012 Intel Corporation
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as

--- 781 unchanged lines hidden (view full) ---

790
791 if (test_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED,
792 &hdev->quirks))
793 settings |= MGMT_SETTING_WIDEBAND_SPEECH;
794 }
795
796 if (lmp_le_capable(hdev)) {
797 settings |= MGMT_SETTING_LE;
1/*
2 BlueZ - Bluetooth protocol stack for Linux
3
4 Copyright (C) 2010 Nokia Corporation
5 Copyright (C) 2011-2012 Intel Corporation
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as

--- 781 unchanged lines hidden (view full) ---

790
791 if (test_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED,
792 &hdev->quirks))
793 settings |= MGMT_SETTING_WIDEBAND_SPEECH;
794 }
795
796 if (lmp_le_capable(hdev)) {
797 settings |= MGMT_SETTING_LE;
798 settings |= MGMT_SETTING_ADVERTISING;
799 settings |= MGMT_SETTING_SECURE_CONN;
800 settings |= MGMT_SETTING_PRIVACY;
801 settings |= MGMT_SETTING_STATIC_ADDRESS;
798 settings |= MGMT_SETTING_SECURE_CONN;
799 settings |= MGMT_SETTING_PRIVACY;
800 settings |= MGMT_SETTING_STATIC_ADDRESS;
801
802 /* When the experimental feature for LL Privacy support is
803 * enabled, then advertising is no longer supported.
804 */
805 if (!hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
806 settings |= MGMT_SETTING_ADVERTISING;
802 }
803
804 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
805 hdev->set_bdaddr)
806 settings |= MGMT_SETTING_CONFIGURATION;
807
808 settings |= MGMT_SETTING_PHY_CONFIGURATION;
809

--- 2944 unchanged lines hidden (view full) ---

3754#endif
3755
3756/* 671b10b5-42c0-4696-9227-eb28d1b049d6 */
3757static const u8 simult_central_periph_uuid[16] = {
3758 0xd6, 0x49, 0xb0, 0xd1, 0x28, 0xeb, 0x27, 0x92,
3759 0x96, 0x46, 0xc0, 0x42, 0xb5, 0x10, 0x1b, 0x67,
3760};
3761
807 }
808
809 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
810 hdev->set_bdaddr)
811 settings |= MGMT_SETTING_CONFIGURATION;
812
813 settings |= MGMT_SETTING_PHY_CONFIGURATION;
814

--- 2944 unchanged lines hidden (view full) ---

3759#endif
3760
3761/* 671b10b5-42c0-4696-9227-eb28d1b049d6 */
3762static const u8 simult_central_periph_uuid[16] = {
3763 0xd6, 0x49, 0xb0, 0xd1, 0x28, 0xeb, 0x27, 0x92,
3764 0x96, 0x46, 0xc0, 0x42, 0xb5, 0x10, 0x1b, 0x67,
3765};
3766
3767/* 15c0a148-c273-11ea-b3de-0242ac130004 */
3768static const u8 rpa_resolution_uuid[16] = {
3769 0x04, 0x00, 0x13, 0xac, 0x42, 0x02, 0xde, 0xb3,
3770 0xea, 0x11, 0x73, 0xc2, 0x48, 0xa1, 0xc0, 0x15,
3771};
3772
3762static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
3763 void *data, u16 data_len)
3764{
3773static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
3774 void *data, u16 data_len)
3775{
3765 char buf[44];
3776 char buf[62]; /* Enough space for 3 features */
3766 struct mgmt_rp_read_exp_features_info *rp = (void *)buf;
3767 u16 idx = 0;
3768 u32 flags;
3769
3770 bt_dev_dbg(hdev, "sock %p", sk);
3771
3772 memset(&buf, 0, sizeof(buf));
3773

--- 16 unchanged lines hidden (view full) ---

3790 else
3791 flags = 0;
3792
3793 memcpy(rp->features[idx].uuid, simult_central_periph_uuid, 16);
3794 rp->features[idx].flags = cpu_to_le32(flags);
3795 idx++;
3796 }
3797
3777 struct mgmt_rp_read_exp_features_info *rp = (void *)buf;
3778 u16 idx = 0;
3779 u32 flags;
3780
3781 bt_dev_dbg(hdev, "sock %p", sk);
3782
3783 memset(&buf, 0, sizeof(buf));
3784

--- 16 unchanged lines hidden (view full) ---

3801 else
3802 flags = 0;
3803
3804 memcpy(rp->features[idx].uuid, simult_central_periph_uuid, 16);
3805 rp->features[idx].flags = cpu_to_le32(flags);
3806 idx++;
3807 }
3808
3809 if (hdev && use_ll_privacy(hdev)) {
3810 if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
3811 flags = BIT(0) | BIT(1);
3812 else
3813 flags = BIT(1);
3814
3815 memcpy(rp->features[idx].uuid, rpa_resolution_uuid, 16);
3816 rp->features[idx].flags = cpu_to_le32(flags);
3817 idx++;
3818 }
3819
3798 rp->feature_count = cpu_to_le16(idx);
3799
3800 /* After reading the experimental features information, enable
3801 * the events to update client on any future change.
3802 */
3803 hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
3804
3805 return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
3806 MGMT_OP_READ_EXP_FEATURES_INFO,
3807 0, rp, sizeof(*rp) + (20 * idx));
3808}
3809
3820 rp->feature_count = cpu_to_le16(idx);
3821
3822 /* After reading the experimental features information, enable
3823 * the events to update client on any future change.
3824 */
3825 hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
3826
3827 return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
3828 MGMT_OP_READ_EXP_FEATURES_INFO,
3829 0, rp, sizeof(*rp) + (20 * idx));
3830}
3831
3832static int exp_ll_privacy_feature_changed(bool enabled, struct hci_dev *hdev,
3833 struct sock *skip)
3834{
3835 struct mgmt_ev_exp_feature_changed ev;
3836
3837 memset(&ev, 0, sizeof(ev));
3838 memcpy(ev.uuid, rpa_resolution_uuid, 16);
3839 ev.flags = cpu_to_le32((enabled ? BIT(0) : 0) | BIT(1));
3840
3841 return mgmt_limited_event(MGMT_EV_EXP_FEATURE_CHANGED, hdev,
3842 &ev, sizeof(ev),
3843 HCI_MGMT_EXP_FEATURE_EVENTS, skip);
3844
3845}
3846
3810#ifdef CONFIG_BT_FEATURE_DEBUG
3811static int exp_debug_feature_changed(bool enabled, struct sock *skip)
3812{
3813 struct mgmt_ev_exp_feature_changed ev;
3814
3815 memset(&ev, 0, sizeof(ev));
3816 memcpy(ev.uuid, debug_uuid, 16);
3817 ev.flags = cpu_to_le32(enabled ? BIT(0) : 0);

--- 22 unchanged lines hidden (view full) ---

3840
3841 bt_dbg_set(false);
3842
3843 if (changed)
3844 exp_debug_feature_changed(false, sk);
3845 }
3846#endif
3847
3847#ifdef CONFIG_BT_FEATURE_DEBUG
3848static int exp_debug_feature_changed(bool enabled, struct sock *skip)
3849{
3850 struct mgmt_ev_exp_feature_changed ev;
3851
3852 memset(&ev, 0, sizeof(ev));
3853 memcpy(ev.uuid, debug_uuid, 16);
3854 ev.flags = cpu_to_le32(enabled ? BIT(0) : 0);

--- 22 unchanged lines hidden (view full) ---

3877
3878 bt_dbg_set(false);
3879
3880 if (changed)
3881 exp_debug_feature_changed(false, sk);
3882 }
3883#endif
3884
3885 if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) {
3886 bool changed = hci_dev_test_flag(hdev,
3887 HCI_ENABLE_LL_PRIVACY);
3888
3889 hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
3890
3891 if (changed)
3892 exp_ll_privacy_feature_changed(false, hdev, sk);
3893 }
3894
3848 hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
3849
3850 return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
3851 MGMT_OP_SET_EXP_FEATURE, 0,
3852 &rp, sizeof(rp));
3853 }
3854
3855#ifdef CONFIG_BT_FEATURE_DEBUG

--- 34 unchanged lines hidden (view full) ---

3890
3891 if (changed)
3892 exp_debug_feature_changed(val, sk);
3893
3894 return err;
3895 }
3896#endif
3897
3895 hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
3896
3897 return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
3898 MGMT_OP_SET_EXP_FEATURE, 0,
3899 &rp, sizeof(rp));
3900 }
3901
3902#ifdef CONFIG_BT_FEATURE_DEBUG

--- 34 unchanged lines hidden (view full) ---

3937
3938 if (changed)
3939 exp_debug_feature_changed(val, sk);
3940
3941 return err;
3942 }
3943#endif
3944
3945 if (!memcmp(cp->uuid, rpa_resolution_uuid, 16)) {
3946 bool val, changed;
3947 int err;
3948 u32 flags;
3949
3950 /* Command requires to use the controller index */
3951 if (!hdev)
3952 return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
3953 MGMT_OP_SET_EXP_FEATURE,
3954 MGMT_STATUS_INVALID_INDEX);
3955
3956 /* Changes can only be made when controller is powered down */
3957 if (hdev_is_powered(hdev))
3958 return mgmt_cmd_status(sk, hdev->id,
3959 MGMT_OP_SET_EXP_FEATURE,
3960 MGMT_STATUS_NOT_POWERED);
3961
3962 /* Parameters are limited to a single octet */
3963 if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
3964 return mgmt_cmd_status(sk, hdev->id,
3965 MGMT_OP_SET_EXP_FEATURE,
3966 MGMT_STATUS_INVALID_PARAMS);
3967
3968 /* Only boolean on/off is supported */
3969 if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
3970 return mgmt_cmd_status(sk, hdev->id,
3971 MGMT_OP_SET_EXP_FEATURE,
3972 MGMT_STATUS_INVALID_PARAMS);
3973
3974 val = !!cp->param[0];
3975
3976 if (val) {
3977 changed = !hci_dev_test_flag(hdev,
3978 HCI_ENABLE_LL_PRIVACY);
3979 hci_dev_set_flag(hdev, HCI_ENABLE_LL_PRIVACY);
3980 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
3981
3982 /* Enable LL privacy + supported settings changed */
3983 flags = BIT(0) | BIT(1);
3984 } else {
3985 changed = hci_dev_test_flag(hdev,
3986 HCI_ENABLE_LL_PRIVACY);
3987 hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
3988
3989 /* Disable LL privacy + supported settings changed */
3990 flags = BIT(1);
3991 }
3992
3993 memcpy(rp.uuid, rpa_resolution_uuid, 16);
3994 rp.flags = cpu_to_le32(flags);
3995
3996 hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
3997
3998 err = mgmt_cmd_complete(sk, hdev->id,
3999 MGMT_OP_SET_EXP_FEATURE, 0,
4000 &rp, sizeof(rp));
4001
4002 if (changed)
4003 exp_ll_privacy_feature_changed(val, hdev, sk);
4004
4005 return err;
4006 }
4007
3898 return mgmt_cmd_status(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
3899 MGMT_OP_SET_EXP_FEATURE,
3900 MGMT_STATUS_NOT_SUPPORTED);
3901}
3902
3903#define SUPPORTED_DEVICE_FLAGS() ((1U << HCI_CONN_FLAG_MAX) - 1)
3904
3905static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,

--- 1129 unchanged lines hidden (view full) ---

5035
5036 bt_dev_dbg(hdev, "sock %p", sk);
5037
5038 status = mgmt_le_support(hdev);
5039 if (status)
5040 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
5041 status);
5042
4008 return mgmt_cmd_status(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
4009 MGMT_OP_SET_EXP_FEATURE,
4010 MGMT_STATUS_NOT_SUPPORTED);
4011}
4012
4013#define SUPPORTED_DEVICE_FLAGS() ((1U << HCI_CONN_FLAG_MAX) - 1)
4014
4015static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,

--- 1129 unchanged lines hidden (view full) ---

5145
5146 bt_dev_dbg(hdev, "sock %p", sk);
5147
5148 status = mgmt_le_support(hdev);
5149 if (status)
5150 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
5151 status);
5152
5153 /* Enabling the experimental LL Privay support disables support for
5154 * advertising.
5155 */
5156 if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
5157 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
5158 MGMT_STATUS_NOT_SUPPORTED);
5159
5043 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
5044 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
5045 MGMT_STATUS_INVALID_PARAMS);
5046
5047 if (hdev->advertising_paused)
5048 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
5049 MGMT_STATUS_BUSY);
5050

--- 2056 unchanged lines hidden (view full) ---

7107 u8 *instance;
7108
7109 bt_dev_dbg(hdev, "sock %p", sk);
7110
7111 if (!lmp_le_capable(hdev))
7112 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
7113 MGMT_STATUS_REJECTED);
7114
5160 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
5161 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
5162 MGMT_STATUS_INVALID_PARAMS);
5163
5164 if (hdev->advertising_paused)
5165 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
5166 MGMT_STATUS_BUSY);
5167

--- 2056 unchanged lines hidden (view full) ---

7224 u8 *instance;
7225
7226 bt_dev_dbg(hdev, "sock %p", sk);
7227
7228 if (!lmp_le_capable(hdev))
7229 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
7230 MGMT_STATUS_REJECTED);
7231
7232 /* Enabling the experimental LL Privay support disables support for
7233 * advertising.
7234 */
7235 if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
7236 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
7237 MGMT_STATUS_NOT_SUPPORTED);
7238
7115 hci_dev_lock(hdev);
7116
7117 rp_len = sizeof(*rp) + hdev->adv_instance_cnt;
7118 rp = kmalloc(rp_len, GFP_ATOMIC);
7119 if (!rp) {
7120 hci_dev_unlock(hdev);
7121 return -ENOMEM;
7122 }

--- 187 unchanged lines hidden (view full) ---

7310
7311 bt_dev_dbg(hdev, "sock %p", sk);
7312
7313 status = mgmt_le_support(hdev);
7314 if (status)
7315 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7316 status);
7317
7239 hci_dev_lock(hdev);
7240
7241 rp_len = sizeof(*rp) + hdev->adv_instance_cnt;
7242 rp = kmalloc(rp_len, GFP_ATOMIC);
7243 if (!rp) {
7244 hci_dev_unlock(hdev);
7245 return -ENOMEM;
7246 }

--- 187 unchanged lines hidden (view full) ---

7434
7435 bt_dev_dbg(hdev, "sock %p", sk);
7436
7437 status = mgmt_le_support(hdev);
7438 if (status)
7439 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7440 status);
7441
7442 /* Enabling the experimental LL Privay support disables support for
7443 * advertising.
7444 */
7445 if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
7446 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
7447 MGMT_STATUS_NOT_SUPPORTED);
7448
7318 if (cp->instance < 1 || cp->instance > HCI_MAX_ADV_INSTANCES)
7319 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7320 MGMT_STATUS_INVALID_PARAMS);
7321
7322 if (data_len != sizeof(*cp) + cp->adv_data_len + cp->scan_rsp_len)
7323 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7324 MGMT_STATUS_INVALID_PARAMS);
7325

--- 148 unchanged lines hidden (view full) ---

7474 struct mgmt_cp_remove_advertising *cp = data;
7475 struct mgmt_rp_remove_advertising rp;
7476 struct mgmt_pending_cmd *cmd;
7477 struct hci_request req;
7478 int err;
7479
7480 bt_dev_dbg(hdev, "sock %p", sk);
7481
7449 if (cp->instance < 1 || cp->instance > HCI_MAX_ADV_INSTANCES)
7450 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7451 MGMT_STATUS_INVALID_PARAMS);
7452
7453 if (data_len != sizeof(*cp) + cp->adv_data_len + cp->scan_rsp_len)
7454 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
7455 MGMT_STATUS_INVALID_PARAMS);
7456

--- 148 unchanged lines hidden (view full) ---

7605 struct mgmt_cp_remove_advertising *cp = data;
7606 struct mgmt_rp_remove_advertising rp;
7607 struct mgmt_pending_cmd *cmd;
7608 struct hci_request req;
7609 int err;
7610
7611 bt_dev_dbg(hdev, "sock %p", sk);
7612
7613 /* Enabling the experimental LL Privay support disables support for
7614 * advertising.
7615 */
7616 if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
7617 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
7618 MGMT_STATUS_NOT_SUPPORTED);
7619
7482 hci_dev_lock(hdev);
7483
7484 if (cp->instance && !hci_find_adv_instance(hdev, cp->instance)) {
7485 err = mgmt_cmd_status(sk, hdev->id,
7486 MGMT_OP_REMOVE_ADVERTISING,
7487 MGMT_STATUS_INVALID_PARAMS);
7488 goto unlock;
7489 }

--- 1259 unchanged lines hidden ---
7620 hci_dev_lock(hdev);
7621
7622 if (cp->instance && !hci_find_adv_instance(hdev, cp->instance)) {
7623 err = mgmt_cmd_status(sk, hdev->id,
7624 MGMT_OP_REMOVE_ADVERTISING,
7625 MGMT_STATUS_INVALID_PARAMS);
7626 goto unlock;
7627 }

--- 1259 unchanged lines hidden ---