This patch takes the min/max intervals and tx power optionally provided
in mgmt interface, stores them in the advertisement struct, and uses
them when configuring the hci requests. While tx power is not used if
extended advertising is unavailable, software rotation will use the min
and max advertising intervals specified by the client.

This change is validated manually by ensuring the min/max intervals are
propagated to the controller on both hatch (extended advertising) and
kukui (no extended advertising) chromebooks, and that tx power is
propagated correctly on hatch. These tests are performed with multiple
advertisements simultaneously.

Reviewed-by: Sonny Sasaka <sonnysas...@chromium.org>
Signed-off-by: Daniel Winkler <danielwink...@google.com>
---

Changes in v7: None
Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 include/net/bluetooth/hci_core.h |  5 ++++-
 net/bluetooth/hci_core.c         |  8 +++++---
 net/bluetooth/hci_request.c      | 29 +++++++++++++++++++----------
 net/bluetooth/mgmt.c             |  8 ++++++--
 4 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3c2e205f226ac6..88988d4fd34750 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -230,6 +230,8 @@ struct adv_info {
        __u16   scan_rsp_len;
        __u8    scan_rsp_data[HCI_MAX_AD_LENGTH];
        __s8    tx_power;
+       __u32   min_interval;
+       __u32   max_interval;
        bdaddr_t        random_addr;
        bool            rpa_expired;
        struct delayed_work     rpa_expired_cb;
@@ -1303,7 +1305,8 @@ struct adv_info *hci_get_next_instance(struct hci_dev 
*hdev, u8 instance);
 int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
                         u16 adv_data_len, u8 *adv_data,
                         u16 scan_rsp_len, u8 *scan_rsp_data,
-                        u16 timeout, u16 duration);
+                        u16 timeout, u16 duration, s8 tx_power,
+                        u32 min_interval, u32 max_interval);
 int hci_set_adv_instance_data(struct hci_dev *hdev, u8 instance,
                         u16 adv_data_len, u8 *adv_data,
                         u16 scan_rsp_len, u8 *scan_rsp_data);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 46ec523d96a76c..8855d07534ed8b 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2951,7 +2951,8 @@ static void adv_instance_rpa_expired(struct work_struct 
*work)
 int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
                         u16 adv_data_len, u8 *adv_data,
                         u16 scan_rsp_len, u8 *scan_rsp_data,
-                        u16 timeout, u16 duration)
+                        u16 timeout, u16 duration, s8 tx_power,
+                        u32 min_interval, u32 max_interval)
 {
        struct adv_info *adv_instance;
 
@@ -2979,6 +2980,9 @@ int hci_add_adv_instance(struct hci_dev *hdev, u8 
instance, u32 flags,
        adv_instance->flags = flags;
        adv_instance->adv_data_len = adv_data_len;
        adv_instance->scan_rsp_len = scan_rsp_len;
+       adv_instance->min_interval = min_interval;
+       adv_instance->max_interval = max_interval;
+       adv_instance->tx_power = tx_power;
 
        if (adv_data_len)
                memcpy(adv_instance->adv_data, adv_data, adv_data_len);
@@ -2995,8 +2999,6 @@ int hci_add_adv_instance(struct hci_dev *hdev, u8 
instance, u32 flags,
        else
                adv_instance->duration = duration;
 
-       adv_instance->tx_power = HCI_TX_POWER_INVALID;
-
        INIT_DELAYED_WORK(&adv_instance->rpa_expired_cb,
                          adv_instance_rpa_expired);
 
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index d0d0fbbb3fa571..80dc451d6e1242 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -1488,6 +1488,7 @@ static bool is_advertising_allowed(struct hci_dev *hdev, 
bool connectable)
 void __hci_req_enable_advertising(struct hci_request *req)
 {
        struct hci_dev *hdev = req->hdev;
+       struct adv_info *adv_instance;
        struct hci_cp_le_set_adv_param cp;
        u8 own_addr_type, enable = 0x01;
        bool connectable;
@@ -1495,6 +1496,7 @@ void __hci_req_enable_advertising(struct hci_request *req)
        u32 flags;
 
        flags = get_adv_instance_flags(hdev, hdev->cur_adv_instance);
+       adv_instance = hci_find_adv_instance(hdev, hdev->cur_adv_instance);
 
        /* If the "connectable" instance flag was not set, then choose between
         * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
@@ -1526,11 +1528,16 @@ void __hci_req_enable_advertising(struct hci_request 
*req)
 
        memset(&cp, 0, sizeof(cp));
 
-       if (connectable) {
-               cp.type = LE_ADV_IND;
-
+       if (adv_instance) {
+               adv_min_interval = adv_instance->min_interval;
+               adv_max_interval = adv_instance->max_interval;
+       } else {
                adv_min_interval = hdev->le_adv_min_interval;
                adv_max_interval = hdev->le_adv_max_interval;
+       }
+
+       if (connectable) {
+               cp.type = LE_ADV_IND;
        } else {
                if (adv_cur_instance_is_scannable(hdev))
                        cp.type = LE_ADV_SCAN_IND;
@@ -1541,9 +1548,6 @@ void __hci_req_enable_advertising(struct hci_request *req)
                    hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE)) {
                        adv_min_interval = DISCOV_LE_FAST_ADV_INT_MIN;
                        adv_max_interval = DISCOV_LE_FAST_ADV_INT_MAX;
-               } else {
-                       adv_min_interval = hdev->le_adv_min_interval;
-                       adv_max_interval = hdev->le_adv_max_interval;
                }
        }
 
@@ -2119,9 +2123,15 @@ int __hci_req_setup_ext_adv_instance(struct hci_request 
*req, u8 instance)
 
        memset(&cp, 0, sizeof(cp));
 
-       /* In ext adv set param interval is 3 octets */
-       hci_cpu_to_le24(hdev->le_adv_min_interval, cp.min_interval);
-       hci_cpu_to_le24(hdev->le_adv_max_interval, cp.max_interval);
+       if (adv_instance) {
+               hci_cpu_to_le24(adv_instance->min_interval, cp.min_interval);
+               hci_cpu_to_le24(adv_instance->max_interval, cp.max_interval);
+               cp.tx_power = adv_instance->tx_power;
+       } else {
+               hci_cpu_to_le24(hdev->le_adv_min_interval, cp.min_interval);
+               hci_cpu_to_le24(hdev->le_adv_max_interval, cp.max_interval);
+               cp.tx_power = HCI_ADV_TX_POWER_NO_PREFERENCE;
+       }
 
        secondary_adv = (flags & MGMT_ADV_FLAG_SEC_MASK);
 
@@ -2144,7 +2154,6 @@ int __hci_req_setup_ext_adv_instance(struct hci_request 
*req, u8 instance)
 
        cp.own_addr_type = own_addr_type;
        cp.channel_map = hdev->le_adv_channel_map;
-       cp.tx_power = 127;
        cp.handle = instance;
 
        if (flags & MGMT_ADV_FLAG_SEC_2M) {
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index ec6b520be368be..668a62c8181eb1 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -7533,7 +7533,10 @@ static int add_advertising(struct sock *sk, struct 
hci_dev *hdev,
                                   cp->adv_data_len, cp->data,
                                   cp->scan_rsp_len,
                                   cp->data + cp->adv_data_len,
-                                  timeout, duration);
+                                  timeout, duration,
+                                  HCI_ADV_TX_POWER_NO_PREFERENCE,
+                                  hdev->le_adv_min_interval,
+                                  hdev->le_adv_max_interval);
        if (err < 0) {
                err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
                                      MGMT_STATUS_FAILED);
@@ -7741,7 +7744,8 @@ static int add_ext_adv_params(struct sock *sk, struct 
hci_dev *hdev,
 
        /* Create advertising instance with no advertising or response data */
        err = hci_add_adv_instance(hdev, cp->instance, flags,
-                                  0, NULL, 0, NULL, timeout, duration);
+                                  0, NULL, 0, NULL, timeout, duration,
+                                  tx_power, min_interval, max_interval);
 
        if (err < 0) {
                err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_PARAMS,
-- 
2.29.2.576.ga3fc446d84-goog

Reply via email to