aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaganath Kanakkassery <jaganath.k.os@gmail.com>2018-07-19 07:39:41 -0400
committerMarcel Holtmann <marcel@holtmann.org>2018-07-30 07:44:52 -0400
commitde181e887ac27dadda127c7d4c3e89c6da8fb6d2 (patch)
tree35722a8b355326084035980d7bd6880a2f34d112
parent6b49bcb4bce2ed0f0aefe8e304a8b9cbaeeaa3f0 (diff)
Bluetooth: Impmlement extended adv enable
This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/hci.h39
-rw-r--r--include/net/bluetooth/hci_core.h1
-rw-r--r--net/bluetooth/hci_core.c2
-rw-r--r--net/bluetooth/hci_event.c72
-rw-r--r--net/bluetooth/hci_request.c171
-rw-r--r--net/bluetooth/hci_request.h3
-rw-r--r--net/bluetooth/mgmt.c22
7 files changed, 285 insertions, 25 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 3f93ae9765a4..b447b127879e 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1586,6 +1586,45 @@ struct hci_rp_le_read_num_supported_adv_sets {
1586 __u8 num_of_sets; 1586 __u8 num_of_sets;
1587} __packed; 1587} __packed;
1588 1588
1589#define HCI_OP_LE_SET_EXT_ADV_PARAMS 0x2036
1590struct hci_cp_le_set_ext_adv_params {
1591 __u8 handle;
1592 __le16 evt_properties;
1593 __u8 min_interval[3];
1594 __u8 max_interval[3];
1595 __u8 channel_map;
1596 __u8 own_addr_type;
1597 __u8 peer_addr_type;
1598 bdaddr_t peer_addr;
1599 __u8 filter_policy;
1600 __u8 tx_power;
1601 __u8 primary_phy;
1602 __u8 secondary_max_skip;
1603 __u8 secondary_phy;
1604 __u8 sid;
1605 __u8 notif_enable;
1606} __packed;
1607
1608#define HCI_ADV_PHY_1M 0X01
1609
1610struct hci_rp_le_set_ext_adv_params {
1611 __u8 status;
1612 __u8 tx_power;
1613} __packed;
1614
1615#define HCI_OP_LE_SET_EXT_ADV_ENABLE 0x2039
1616struct hci_cp_le_set_ext_adv_enable {
1617 __u8 enable;
1618 __u8 num_of_sets;
1619 __u8 data[0];
1620} __packed;
1621
1622struct hci_cp_ext_adv_set {
1623 __u8 handle;
1624 __le16 duration;
1625 __u8 max_events;
1626} __packed;
1627
1589/* ---- HCI Events ---- */ 1628/* ---- HCI Events ---- */
1590#define HCI_EV_INQUIRY_COMPLETE 0x01 1629#define HCI_EV_INQUIRY_COMPLETE 0x01
1591 1630
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 2aad4a863176..ad3518303a0c 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -171,6 +171,7 @@ struct adv_info {
171 __u8 adv_data[HCI_MAX_AD_LENGTH]; 171 __u8 adv_data[HCI_MAX_AD_LENGTH];
172 __u16 scan_rsp_len; 172 __u16 scan_rsp_len;
173 __u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; 173 __u8 scan_rsp_data[HCI_MAX_AD_LENGTH];
174 __s8 tx_power;
174}; 175};
175 176
176#define HCI_MAX_ADV_INSTANCES 5 177#define HCI_MAX_ADV_INSTANCES 5
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 7b08b7f57418..944d4fedc317 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2779,6 +2779,8 @@ int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
2779 else 2779 else
2780 adv_instance->duration = duration; 2780 adv_instance->duration = duration;
2781 2781
2782 adv_instance->tx_power = HCI_TX_POWER_INVALID;
2783
2782 BT_DBG("%s for %dMR", hdev->name, instance); 2784 BT_DBG("%s for %dMR", hdev->name, instance);
2783 2785
2784 return 0; 2786 return 0;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0ceb52edc142..0418a5514819 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1099,6 +1099,41 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
1099 hci_dev_unlock(hdev); 1099 hci_dev_unlock(hdev);
1100} 1100}
1101 1101
1102static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev,
1103 struct sk_buff *skb)
1104{
1105 struct hci_cp_le_set_ext_adv_enable *cp;
1106 struct hci_cp_ext_adv_set *adv_set;
1107 __u8 status = *((__u8 *) skb->data);
1108
1109 BT_DBG("%s status 0x%2.2x", hdev->name, status);
1110
1111 if (status)
1112 return;
1113
1114 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE);
1115 if (!cp)
1116 return;
1117
1118 adv_set = (void *) cp->data;
1119
1120 hci_dev_lock(hdev);
1121
1122 if (cp->enable) {
1123 struct hci_conn *conn;
1124
1125 hci_dev_set_flag(hdev, HCI_LE_ADV);
1126
1127 conn = hci_lookup_le_connect(hdev);
1128 if (conn)
1129 queue_delayed_work(hdev->workqueue,
1130 &conn->le_conn_timeout,
1131 conn->conn_timeout);
1132 }
1133
1134 hci_dev_unlock(hdev);
1135}
1136
1102static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 1137static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
1103{ 1138{
1104 struct hci_cp_le_set_scan_param *cp; 1139 struct hci_cp_le_set_scan_param *cp;
@@ -1486,6 +1521,35 @@ static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
1486 hci_dev_unlock(hdev); 1521 hci_dev_unlock(hdev);
1487} 1522}
1488 1523
1524static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
1525{
1526 struct hci_rp_le_set_ext_adv_params *rp = (void *) skb->data;
1527 struct hci_cp_le_set_ext_adv_params *cp;
1528 struct adv_info *adv_instance;
1529
1530 BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
1531
1532 if (rp->status)
1533 return;
1534
1535 cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS);
1536 if (!cp)
1537 return;
1538
1539 hci_dev_lock(hdev);
1540 hdev->adv_addr_type = cp->own_addr_type;
1541 if (!hdev->cur_adv_instance) {
1542 /* Store in hdev for instance 0 */
1543 hdev->adv_tx_power = rp->tx_power;
1544 } else {
1545 adv_instance = hci_find_adv_instance(hdev,
1546 hdev->cur_adv_instance);
1547 if (adv_instance)
1548 adv_instance->tx_power = rp->tx_power;
1549 }
1550 hci_dev_unlock(hdev);
1551}
1552
1489static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) 1553static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb)
1490{ 1554{
1491 struct hci_rp_read_rssi *rp = (void *) skb->data; 1555 struct hci_rp_read_rssi *rp = (void *) skb->data;
@@ -3207,6 +3271,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
3207 hci_cc_le_read_num_adv_sets(hdev, skb); 3271 hci_cc_le_read_num_adv_sets(hdev, skb);
3208 break; 3272 break;
3209 3273
3274 case HCI_OP_LE_SET_EXT_ADV_PARAMS:
3275 hci_cc_set_ext_adv_param(hdev, skb);
3276 break;
3277
3278 case HCI_OP_LE_SET_EXT_ADV_ENABLE:
3279 hci_cc_le_set_ext_adv_enable(hdev, skb);
3280 break;
3281
3210 default: 3282 default:
3211 BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode); 3283 BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
3212 break; 3284 break;
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 215059a7646e..2ac9fd67440a 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -895,6 +895,24 @@ void hci_req_add_le_passive_scan(struct hci_request *req)
895 hdev->le_scan_window, own_addr_type, filter_policy); 895 hdev->le_scan_window, own_addr_type, filter_policy);
896} 896}
897 897
898static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance)
899{
900 struct adv_info *adv_instance;
901
902 /* Ignore instance 0 */
903 if (instance == 0x00)
904 return 0;
905
906 adv_instance = hci_find_adv_instance(hdev, instance);
907 if (!adv_instance)
908 return 0;
909
910 /* TODO: Take into account the "appearance" and "local-name" flags here.
911 * These are currently being ignored as they are not supported.
912 */
913 return adv_instance->scan_rsp_len;
914}
915
898static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev) 916static u8 get_cur_adv_instance_scan_rsp_len(struct hci_dev *hdev)
899{ 917{
900 u8 instance = hdev->cur_adv_instance; 918 u8 instance = hdev->cur_adv_instance;
@@ -1235,15 +1253,27 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
1235 ptr += adv_instance->adv_data_len; 1253 ptr += adv_instance->adv_data_len;
1236 } 1254 }
1237 1255
1238 /* Provide Tx Power only if we can provide a valid value for it */ 1256 if (instance_flags & MGMT_ADV_FLAG_TX_POWER) {
1239 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID && 1257 s8 adv_tx_power;
1240 (instance_flags & MGMT_ADV_FLAG_TX_POWER)) {
1241 ptr[0] = 0x02;
1242 ptr[1] = EIR_TX_POWER;
1243 ptr[2] = (u8)hdev->adv_tx_power;
1244 1258
1245 ad_len += 3; 1259 if (ext_adv_capable(hdev)) {
1246 ptr += 3; 1260 if (adv_instance)
1261 adv_tx_power = adv_instance->tx_power;
1262 else
1263 adv_tx_power = hdev->adv_tx_power;
1264 } else {
1265 adv_tx_power = hdev->adv_tx_power;
1266 }
1267
1268 /* Provide Tx Power only if we can provide a valid value for it */
1269 if (adv_tx_power != HCI_TX_POWER_INVALID) {
1270 ptr[0] = 0x02;
1271 ptr[1] = EIR_TX_POWER;
1272 ptr[2] = (u8)adv_tx_power;
1273
1274 ad_len += 3;
1275 ptr += 3;
1276 }
1247 } 1277 }
1248 1278
1249 return ad_len; 1279 return ad_len;
@@ -1304,9 +1334,13 @@ void hci_req_reenable_advertising(struct hci_dev *hdev)
1304 __hci_req_schedule_adv_instance(&req, hdev->cur_adv_instance, 1334 __hci_req_schedule_adv_instance(&req, hdev->cur_adv_instance,
1305 true); 1335 true);
1306 } else { 1336 } else {
1307 __hci_req_update_adv_data(&req, 0x00); 1337 if (ext_adv_capable(hdev)) {
1308 __hci_req_update_scan_rsp_data(&req, 0x00); 1338 __hci_req_start_ext_adv(&req, 0x00);
1309 __hci_req_enable_advertising(&req); 1339 } else {
1340 __hci_req_update_adv_data(&req, 0x00);
1341 __hci_req_update_scan_rsp_data(&req, 0x00);
1342 __hci_req_enable_advertising(&req);
1343 }
1310 } 1344 }
1311 1345
1312 hci_req_run(&req, adv_enable_complete); 1346 hci_req_run(&req, adv_enable_complete);
@@ -1343,6 +1377,87 @@ unlock:
1343 hci_dev_unlock(hdev); 1377 hci_dev_unlock(hdev);
1344} 1378}
1345 1379
1380static int __hci_req_setup_ext_adv_instance(struct hci_request *req,
1381 u8 instance)
1382{
1383 struct hci_cp_le_set_ext_adv_params cp;
1384 struct hci_dev *hdev = req->hdev;
1385 bool connectable;
1386 u32 flags;
1387 /* In ext adv set param interval is 3 octets */
1388 const u8 adv_interval[3] = { 0x00, 0x08, 0x00 };
1389
1390 flags = get_adv_instance_flags(hdev, instance);
1391
1392 /* If the "connectable" instance flag was not set, then choose between
1393 * ADV_IND and ADV_NONCONN_IND based on the global connectable setting.
1394 */
1395 connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
1396 mgmt_get_connectable(hdev);
1397
1398 if (!is_advertising_allowed(hdev, connectable))
1399 return -EPERM;
1400
1401 memset(&cp, 0, sizeof(cp));
1402
1403 memcpy(cp.min_interval, adv_interval, sizeof(cp.min_interval));
1404 memcpy(cp.max_interval, adv_interval, sizeof(cp.max_interval));
1405
1406 if (connectable)
1407 cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_IND);
1408 else if (get_adv_instance_scan_rsp_len(hdev, instance))
1409 cp.evt_properties = cpu_to_le16(LE_LEGACY_ADV_SCAN_IND);
1410 else
1411 cp.evt_properties = cpu_to_le16(LE_LEGACY_NONCONN_IND);
1412
1413 cp.own_addr_type = BDADDR_LE_PUBLIC;
1414 cp.channel_map = hdev->le_adv_channel_map;
1415 cp.tx_power = 127;
1416 cp.primary_phy = HCI_ADV_PHY_1M;
1417 cp.secondary_phy = HCI_ADV_PHY_1M;
1418 cp.handle = 0;
1419
1420 hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(cp), &cp);
1421
1422 return 0;
1423}
1424
1425void __hci_req_enable_ext_advertising(struct hci_request *req)
1426{
1427 struct hci_cp_le_set_ext_adv_enable *cp;
1428 struct hci_cp_ext_adv_set *adv_set;
1429 u8 data[sizeof(*cp) + sizeof(*adv_set) * 1];
1430
1431 cp = (void *) data;
1432 adv_set = (void *) cp->data;
1433
1434 memset(cp, 0, sizeof(*cp));
1435
1436 cp->enable = 0x01;
1437 cp->num_of_sets = 0x01;
1438
1439 memset(adv_set, 0, sizeof(*adv_set));
1440
1441 adv_set->handle = 0;
1442
1443 hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE,
1444 sizeof(*cp) + sizeof(*adv_set) * cp->num_of_sets,
1445 data);
1446}
1447
1448int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
1449{
1450 int err;
1451
1452 err = __hci_req_setup_ext_adv_instance(req, instance);
1453 if (err < 0)
1454 return err;
1455
1456 __hci_req_enable_ext_advertising(req);
1457
1458 return 0;
1459}
1460
1346int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance, 1461int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
1347 bool force) 1462 bool force)
1348{ 1463{
@@ -1396,9 +1511,13 @@ int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
1396 return 0; 1511 return 0;
1397 1512
1398 hdev->cur_adv_instance = instance; 1513 hdev->cur_adv_instance = instance;
1399 __hci_req_update_adv_data(req, instance); 1514 if (ext_adv_capable(hdev)) {
1400 __hci_req_update_scan_rsp_data(req, instance); 1515 __hci_req_start_ext_adv(req, instance);
1401 __hci_req_enable_advertising(req); 1516 } else {
1517 __hci_req_update_adv_data(req, instance);
1518 __hci_req_update_scan_rsp_data(req, instance);
1519 __hci_req_enable_advertising(req);
1520 }
1402 1521
1403 return 0; 1522 return 0;
1404} 1523}
@@ -1669,8 +1788,12 @@ static int connectable_update(struct hci_request *req, unsigned long opt)
1669 1788
1670 /* Update the advertising parameters if necessary */ 1789 /* Update the advertising parameters if necessary */
1671 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || 1790 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
1672 !list_empty(&hdev->adv_instances)) 1791 !list_empty(&hdev->adv_instances)) {
1673 __hci_req_enable_advertising(req); 1792 if (ext_adv_capable(hdev))
1793 __hci_req_start_ext_adv(req, hdev->cur_adv_instance);
1794 else
1795 __hci_req_enable_advertising(req);
1796 }
1674 1797
1675 __hci_update_background_scan(req); 1798 __hci_update_background_scan(req);
1676 1799
@@ -1779,8 +1902,12 @@ static int discoverable_update(struct hci_request *req, unsigned long opt)
1779 /* Discoverable mode affects the local advertising 1902 /* Discoverable mode affects the local advertising
1780 * address in limited privacy mode. 1903 * address in limited privacy mode.
1781 */ 1904 */
1782 if (hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) 1905 if (hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) {
1783 __hci_req_enable_advertising(req); 1906 if (ext_adv_capable(hdev))
1907 __hci_req_start_ext_adv(req, 0x00);
1908 else
1909 __hci_req_enable_advertising(req);
1910 }
1784 } 1911 }
1785 1912
1786 hci_dev_unlock(hdev); 1913 hci_dev_unlock(hdev);
@@ -2376,8 +2503,12 @@ static int powered_update_hci(struct hci_request *req, unsigned long opt)
2376 __hci_req_update_adv_data(req, 0x00); 2503 __hci_req_update_adv_data(req, 0x00);
2377 __hci_req_update_scan_rsp_data(req, 0x00); 2504 __hci_req_update_scan_rsp_data(req, 0x00);
2378 2505
2379 if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) 2506 if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
2380 __hci_req_enable_advertising(req); 2507 if (ext_adv_capable(hdev))
2508 __hci_req_start_ext_adv(req, 0x00);
2509 else
2510 __hci_req_enable_advertising(req);
2511 }
2381 } else if (!list_empty(&hdev->adv_instances)) { 2512 } else if (!list_empty(&hdev->adv_instances)) {
2382 struct adv_info *adv_instance; 2513 struct adv_info *adv_instance;
2383 2514
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
index 702beb140d9f..9b8c74df6b2b 100644
--- a/net/bluetooth/hci_request.h
+++ b/net/bluetooth/hci_request.h
@@ -80,6 +80,9 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
80 struct hci_request *req, u8 instance, 80 struct hci_request *req, u8 instance,
81 bool force); 81 bool force);
82 82
83int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
84void __hci_req_enable_ext_advertising(struct hci_request *req);
85
83void __hci_req_update_class(struct hci_request *req); 86void __hci_req_update_class(struct hci_request *req);
84 87
85/* Returns true if HCI commands were queued */ 88/* Returns true if HCI commands were queued */
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 1867aadc5061..761a9aeaa824 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -940,7 +940,10 @@ static void rpa_expired(struct work_struct *work)
940 * function. 940 * function.
941 */ 941 */
942 hci_req_init(&req, hdev); 942 hci_req_init(&req, hdev);
943 __hci_req_enable_advertising(&req); 943 if (ext_adv_capable(hdev))
944 __hci_req_start_ext_adv(&req, hdev->cur_adv_instance);
945 else
946 __hci_req_enable_advertising(&req);
944 hci_req_run(&req, NULL); 947 hci_req_run(&req, NULL);
945} 948}
946 949
@@ -4382,9 +4385,14 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4382 * HCI_ADVERTISING flag is not yet set. 4385 * HCI_ADVERTISING flag is not yet set.
4383 */ 4386 */
4384 hdev->cur_adv_instance = 0x00; 4387 hdev->cur_adv_instance = 0x00;
4385 __hci_req_update_adv_data(&req, 0x00); 4388
4386 __hci_req_update_scan_rsp_data(&req, 0x00); 4389 if (ext_adv_capable(hdev)) {
4387 __hci_req_enable_advertising(&req); 4390 __hci_req_start_ext_adv(&req, 0x00);
4391 } else {
4392 __hci_req_update_adv_data(&req, 0x00);
4393 __hci_req_update_scan_rsp_data(&req, 0x00);
4394 __hci_req_enable_advertising(&req);
4395 }
4388 } else { 4396 } else {
4389 __hci_req_disable_advertising(&req); 4397 __hci_req_disable_advertising(&req);
4390 } 4398 }
@@ -6312,7 +6320,11 @@ static u32 get_supported_adv_flags(struct hci_dev *hdev)
6312 flags |= MGMT_ADV_FLAG_APPEARANCE; 6320 flags |= MGMT_ADV_FLAG_APPEARANCE;
6313 flags |= MGMT_ADV_FLAG_LOCAL_NAME; 6321 flags |= MGMT_ADV_FLAG_LOCAL_NAME;
6314 6322
6315 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) 6323 /* In extended adv TX_POWER returned from Set Adv Param
6324 * will be always valid.
6325 */
6326 if ((hdev->adv_tx_power != HCI_TX_POWER_INVALID) ||
6327 ext_adv_capable(hdev))
6316 flags |= MGMT_ADV_FLAG_TX_POWER; 6328 flags |= MGMT_ADV_FLAG_TX_POWER;
6317 6329
6318 return flags; 6330 return flags;