aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_request.c
diff options
context:
space:
mode:
authorJaganath Kanakkassery <jaganath.k.os@gmail.com>2018-07-19 07:39:42 -0400
committerMarcel Holtmann <marcel@holtmann.org>2018-07-30 07:44:52 -0400
commita0fb3726ba55138ef6fdd5dc67da6d9a70360696 (patch)
tree85a4b590c2ef41b8eac7fcc48b88739cf1c285f8 /net/bluetooth/hci_request.c
parentde181e887ac27dadda127c7d4c3e89c6da8fb6d2 (diff)
Bluetooth: Use Set ext adv/scan rsp data if controller supports
This patch implements Set Ext Adv data and Set Ext Scan rsp data if controller support extended advertising. Currently the operation is set as Complete data and fragment preference is set as no fragment < HCI Command: LE Set Extended Advertising Data (0x08|0x0037) plen 35 Handle: 0x00 Operation: Complete extended advertising data (0x03) Fragment preference: Minimize fragmentation (0x01) Data length: 0x15 16-bit Service UUIDs (complete): 2 entries Heart Rate (0x180d) Battery Service (0x180f) Name (complete): Test LE Company: Google (224) Data: 0102 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Data (0x08|0x0037) ncmd 1 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/hci_request.c')
-rw-r--r--net/bluetooth/hci_request.c126
1 files changed, 95 insertions, 31 deletions
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 2ac9fd67440a..c41e9bb7818b 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -1174,29 +1174,58 @@ static u8 create_instance_scan_rsp_data(struct hci_dev *hdev, u8 instance,
1174void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance) 1174void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance)
1175{ 1175{
1176 struct hci_dev *hdev = req->hdev; 1176 struct hci_dev *hdev = req->hdev;
1177 struct hci_cp_le_set_scan_rsp_data cp;
1178 u8 len; 1177 u8 len;
1179 1178
1180 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) 1179 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
1181 return; 1180 return;
1182 1181
1183 memset(&cp, 0, sizeof(cp)); 1182 if (ext_adv_capable(hdev)) {
1183 struct hci_cp_le_set_ext_scan_rsp_data cp;
1184 1184
1185 if (instance) 1185 memset(&cp, 0, sizeof(cp));
1186 len = create_instance_scan_rsp_data(hdev, instance, cp.data);
1187 else
1188 len = create_default_scan_rsp_data(hdev, cp.data);
1189 1186
1190 if (hdev->scan_rsp_data_len == len && 1187 if (instance)
1191 !memcmp(cp.data, hdev->scan_rsp_data, len)) 1188 len = create_instance_scan_rsp_data(hdev, instance,
1192 return; 1189 cp.data);
1190 else
1191 len = create_default_scan_rsp_data(hdev, cp.data);
1192
1193 if (hdev->scan_rsp_data_len == len &&
1194 !memcmp(cp.data, hdev->scan_rsp_data, len))
1195 return;
1196
1197 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
1198 hdev->scan_rsp_data_len = len;
1199
1200 cp.handle = 0;
1201 cp.length = len;
1202 cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
1203 cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
1204
1205 hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA, sizeof(cp),
1206 &cp);
1207 } else {
1208 struct hci_cp_le_set_scan_rsp_data cp;
1209
1210 memset(&cp, 0, sizeof(cp));
1211
1212 if (instance)
1213 len = create_instance_scan_rsp_data(hdev, instance,
1214 cp.data);
1215 else
1216 len = create_default_scan_rsp_data(hdev, cp.data);
1217
1218 if (hdev->scan_rsp_data_len == len &&
1219 !memcmp(cp.data, hdev->scan_rsp_data, len))
1220 return;
1193 1221
1194 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data)); 1222 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
1195 hdev->scan_rsp_data_len = len; 1223 hdev->scan_rsp_data_len = len;
1196 1224
1197 cp.length = len; 1225 cp.length = len;
1198 1226
1199 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp); 1227 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
1228 }
1200} 1229}
1201 1230
1202static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) 1231static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
@@ -1282,27 +1311,51 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
1282void __hci_req_update_adv_data(struct hci_request *req, u8 instance) 1311void __hci_req_update_adv_data(struct hci_request *req, u8 instance)
1283{ 1312{
1284 struct hci_dev *hdev = req->hdev; 1313 struct hci_dev *hdev = req->hdev;
1285 struct hci_cp_le_set_adv_data cp;
1286 u8 len; 1314 u8 len;
1287 1315
1288 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) 1316 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
1289 return; 1317 return;
1290 1318
1291 memset(&cp, 0, sizeof(cp)); 1319 if (ext_adv_capable(hdev)) {
1320 struct hci_cp_le_set_ext_adv_data cp;
1292 1321
1293 len = create_instance_adv_data(hdev, instance, cp.data); 1322 memset(&cp, 0, sizeof(cp));
1294 1323
1295 /* There's nothing to do if the data hasn't changed */ 1324 len = create_instance_adv_data(hdev, instance, cp.data);
1296 if (hdev->adv_data_len == len && 1325
1297 memcmp(cp.data, hdev->adv_data, len) == 0) 1326 /* There's nothing to do if the data hasn't changed */
1298 return; 1327 if (hdev->adv_data_len == len &&
1328 memcmp(cp.data, hdev->adv_data, len) == 0)
1329 return;
1330
1331 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1332 hdev->adv_data_len = len;
1333
1334 cp.length = len;
1335 cp.handle = 0;
1336 cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
1337 cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
1299 1338
1300 memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); 1339 hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_DATA, sizeof(cp), &cp);
1301 hdev->adv_data_len = len; 1340 } else {
1341 struct hci_cp_le_set_adv_data cp;
1342
1343 memset(&cp, 0, sizeof(cp));
1302 1344
1303 cp.length = len; 1345 len = create_instance_adv_data(hdev, instance, cp.data);
1346
1347 /* There's nothing to do if the data hasn't changed */
1348 if (hdev->adv_data_len == len &&
1349 memcmp(cp.data, hdev->adv_data, len) == 0)
1350 return;
1304 1351
1305 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); 1352 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1353 hdev->adv_data_len = len;
1354
1355 cp.length = len;
1356
1357 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1358 }
1306} 1359}
1307 1360
1308int hci_req_update_adv_data(struct hci_dev *hdev, u8 instance) 1361int hci_req_update_adv_data(struct hci_dev *hdev, u8 instance)
@@ -1377,8 +1430,7 @@ unlock:
1377 hci_dev_unlock(hdev); 1430 hci_dev_unlock(hdev);
1378} 1431}
1379 1432
1380static int __hci_req_setup_ext_adv_instance(struct hci_request *req, 1433int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
1381 u8 instance)
1382{ 1434{
1383 struct hci_cp_le_set_ext_adv_params cp; 1435 struct hci_cp_le_set_ext_adv_params cp;
1384 struct hci_dev *hdev = req->hdev; 1436 struct hci_dev *hdev = req->hdev;
@@ -1453,6 +1505,7 @@ int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
1453 if (err < 0) 1505 if (err < 0)
1454 return err; 1506 return err;
1455 1507
1508 __hci_req_update_scan_rsp_data(req, instance);
1456 __hci_req_enable_ext_advertising(req); 1509 __hci_req_enable_ext_advertising(req);
1457 1510
1458 return 0; 1511 return 0;
@@ -2500,14 +2553,25 @@ static int powered_update_hci(struct hci_request *req, unsigned long opt)
2500 */ 2553 */
2501 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || 2554 if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
2502 list_empty(&hdev->adv_instances)) { 2555 list_empty(&hdev->adv_instances)) {
2503 __hci_req_update_adv_data(req, 0x00); 2556 int err;
2504 __hci_req_update_scan_rsp_data(req, 0x00); 2557
2558 if (ext_adv_capable(hdev)) {
2559 err = __hci_req_setup_ext_adv_instance(req,
2560 0x00);
2561 if (!err)
2562 __hci_req_update_scan_rsp_data(req,
2563 0x00);
2564 } else {
2565 err = 0;
2566 __hci_req_update_adv_data(req, 0x00);
2567 __hci_req_update_scan_rsp_data(req, 0x00);
2568 }
2505 2569
2506 if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) { 2570 if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
2507 if (ext_adv_capable(hdev)) 2571 if (!ext_adv_capable(hdev))
2508 __hci_req_start_ext_adv(req, 0x00);
2509 else
2510 __hci_req_enable_advertising(req); 2572 __hci_req_enable_advertising(req);
2573 else if (!err)
2574 __hci_req_enable_ext_advertising(req);
2511 } 2575 }
2512 } else if (!list_empty(&hdev->adv_instances)) { 2576 } else if (!list_empty(&hdev->adv_instances)) {
2513 struct adv_info *adv_instance; 2577 struct adv_info *adv_instance;