diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2015-11-22 09:24:44 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-12-09 18:51:48 -0500 |
commit | aed1a8851db022c3bd22af41a343068b8c6e40c1 (patch) | |
tree | 74efd21f8ee36965782e8394cb0e8ee70aa598aa /net/bluetooth | |
parent | 14bf5eac7a4f4bf0729ff8eb358de4fab967cee1 (diff) |
Bluetooth: Move discoverable changes to hdev->req_workqueue
The discoverable mode is intrinsically linked with the connectable
mode e.g. through sharing the same HCI command (Write Scan Enable) for
BR/EDR. It makes therefore sense to move it to hci_request.c and run
the changes through the same hdev->req_workqueue.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hci_request.c | 64 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 90 |
2 files changed, 77 insertions, 77 deletions
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index e5e827b762b9..8f72218ed805 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c | |||
@@ -1351,6 +1351,68 @@ void __hci_req_update_class(struct hci_request *req) | |||
1351 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); | 1351 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); |
1352 | } | 1352 | } |
1353 | 1353 | ||
1354 | static void write_iac(struct hci_request *req) | ||
1355 | { | ||
1356 | struct hci_dev *hdev = req->hdev; | ||
1357 | struct hci_cp_write_current_iac_lap cp; | ||
1358 | |||
1359 | if (!hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) | ||
1360 | return; | ||
1361 | |||
1362 | if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE)) { | ||
1363 | /* Limited discoverable mode */ | ||
1364 | cp.num_iac = min_t(u8, hdev->num_iac, 2); | ||
1365 | cp.iac_lap[0] = 0x00; /* LIAC */ | ||
1366 | cp.iac_lap[1] = 0x8b; | ||
1367 | cp.iac_lap[2] = 0x9e; | ||
1368 | cp.iac_lap[3] = 0x33; /* GIAC */ | ||
1369 | cp.iac_lap[4] = 0x8b; | ||
1370 | cp.iac_lap[5] = 0x9e; | ||
1371 | } else { | ||
1372 | /* General discoverable mode */ | ||
1373 | cp.num_iac = 1; | ||
1374 | cp.iac_lap[0] = 0x33; /* GIAC */ | ||
1375 | cp.iac_lap[1] = 0x8b; | ||
1376 | cp.iac_lap[2] = 0x9e; | ||
1377 | } | ||
1378 | |||
1379 | hci_req_add(req, HCI_OP_WRITE_CURRENT_IAC_LAP, | ||
1380 | (cp.num_iac * 3) + 1, &cp); | ||
1381 | } | ||
1382 | |||
1383 | static int discoverable_update(struct hci_request *req, unsigned long opt) | ||
1384 | { | ||
1385 | struct hci_dev *hdev = req->hdev; | ||
1386 | |||
1387 | hci_dev_lock(hdev); | ||
1388 | |||
1389 | if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) { | ||
1390 | write_iac(req); | ||
1391 | __hci_req_update_scan(req); | ||
1392 | __hci_req_update_class(req); | ||
1393 | } | ||
1394 | |||
1395 | /* Advertising instances don't use the global discoverable setting, so | ||
1396 | * only update AD if advertising was enabled using Set Advertising. | ||
1397 | */ | ||
1398 | if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) | ||
1399 | __hci_req_update_adv_data(req, HCI_ADV_CURRENT); | ||
1400 | |||
1401 | hci_dev_unlock(hdev); | ||
1402 | |||
1403 | return 0; | ||
1404 | } | ||
1405 | |||
1406 | static void discoverable_update_work(struct work_struct *work) | ||
1407 | { | ||
1408 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
1409 | discoverable_update); | ||
1410 | u8 status; | ||
1411 | |||
1412 | hci_req_sync(hdev, discoverable_update, 0, HCI_CMD_TIMEOUT, &status); | ||
1413 | mgmt_set_discoverable_complete(hdev, status); | ||
1414 | } | ||
1415 | |||
1354 | void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn, | 1416 | void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn, |
1355 | u8 reason) | 1417 | u8 reason) |
1356 | { | 1418 | { |
@@ -1867,6 +1929,7 @@ void hci_request_setup(struct hci_dev *hdev) | |||
1867 | INIT_WORK(&hdev->bg_scan_update, bg_scan_update); | 1929 | INIT_WORK(&hdev->bg_scan_update, bg_scan_update); |
1868 | INIT_WORK(&hdev->scan_update, scan_update_work); | 1930 | INIT_WORK(&hdev->scan_update, scan_update_work); |
1869 | INIT_WORK(&hdev->connectable_update, connectable_update_work); | 1931 | INIT_WORK(&hdev->connectable_update, connectable_update_work); |
1932 | INIT_WORK(&hdev->discoverable_update, discoverable_update_work); | ||
1870 | INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work); | 1933 | INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work); |
1871 | INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart_work); | 1934 | INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart_work); |
1872 | INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire); | 1935 | INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire); |
@@ -1880,6 +1943,7 @@ void hci_request_cancel_all(struct hci_dev *hdev) | |||
1880 | cancel_work_sync(&hdev->bg_scan_update); | 1943 | cancel_work_sync(&hdev->bg_scan_update); |
1881 | cancel_work_sync(&hdev->scan_update); | 1944 | cancel_work_sync(&hdev->scan_update); |
1882 | cancel_work_sync(&hdev->connectable_update); | 1945 | cancel_work_sync(&hdev->connectable_update); |
1946 | cancel_work_sync(&hdev->discoverable_update); | ||
1883 | cancel_delayed_work_sync(&hdev->le_scan_disable); | 1947 | cancel_delayed_work_sync(&hdev->le_scan_disable); |
1884 | cancel_delayed_work_sync(&hdev->le_scan_restart); | 1948 | cancel_delayed_work_sync(&hdev->le_scan_restart); |
1885 | 1949 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f5a4ee92f2bf..8846cb3b0aaa 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1282,13 +1282,9 @@ static u8 mgmt_le_support(struct hci_dev *hdev) | |||
1282 | return MGMT_STATUS_SUCCESS; | 1282 | return MGMT_STATUS_SUCCESS; |
1283 | } | 1283 | } |
1284 | 1284 | ||
1285 | static void set_discoverable_complete(struct hci_dev *hdev, u8 status, | 1285 | void mgmt_set_discoverable_complete(struct hci_dev *hdev, u8 status) |
1286 | u16 opcode) | ||
1287 | { | 1286 | { |
1288 | struct mgmt_pending_cmd *cmd; | 1287 | struct mgmt_pending_cmd *cmd; |
1289 | struct mgmt_mode *cp; | ||
1290 | struct hci_request req; | ||
1291 | bool changed; | ||
1292 | 1288 | ||
1293 | BT_DBG("status 0x%02x", status); | 1289 | BT_DBG("status 0x%02x", status); |
1294 | 1290 | ||
@@ -1305,33 +1301,14 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status, | |||
1305 | goto remove_cmd; | 1301 | goto remove_cmd; |
1306 | } | 1302 | } |
1307 | 1303 | ||
1308 | cp = cmd->param; | 1304 | if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE) && |
1309 | if (cp->val) { | 1305 | hdev->discov_timeout > 0) { |
1310 | changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE); | 1306 | int to = msecs_to_jiffies(hdev->discov_timeout * 1000); |
1311 | 1307 | queue_delayed_work(hdev->req_workqueue, &hdev->discov_off, to); | |
1312 | if (hdev->discov_timeout > 0) { | ||
1313 | int to = msecs_to_jiffies(hdev->discov_timeout * 1000); | ||
1314 | queue_delayed_work(hdev->workqueue, &hdev->discov_off, | ||
1315 | to); | ||
1316 | } | ||
1317 | } else { | ||
1318 | changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE); | ||
1319 | } | 1308 | } |
1320 | 1309 | ||
1321 | send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev); | 1310 | send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev); |
1322 | 1311 | new_settings(hdev, cmd->sk); | |
1323 | if (changed) | ||
1324 | new_settings(hdev, cmd->sk); | ||
1325 | |||
1326 | /* When the discoverable mode gets changed, make sure | ||
1327 | * that class of device has the limited discoverable | ||
1328 | * bit correctly set. Also update page scan based on whitelist | ||
1329 | * entries. | ||
1330 | */ | ||
1331 | hci_req_init(&req, hdev); | ||
1332 | __hci_req_update_scan(&req); | ||
1333 | __hci_req_update_class(&req); | ||
1334 | hci_req_run(&req, NULL); | ||
1335 | 1312 | ||
1336 | remove_cmd: | 1313 | remove_cmd: |
1337 | mgmt_pending_remove(cmd); | 1314 | mgmt_pending_remove(cmd); |
@@ -1345,9 +1322,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1345 | { | 1322 | { |
1346 | struct mgmt_cp_set_discoverable *cp = data; | 1323 | struct mgmt_cp_set_discoverable *cp = data; |
1347 | struct mgmt_pending_cmd *cmd; | 1324 | struct mgmt_pending_cmd *cmd; |
1348 | struct hci_request req; | ||
1349 | u16 timeout; | 1325 | u16 timeout; |
1350 | u8 scan; | ||
1351 | int err; | 1326 | int err; |
1352 | 1327 | ||
1353 | BT_DBG("request for %s", hdev->name); | 1328 | BT_DBG("request for %s", hdev->name); |
@@ -1447,58 +1422,19 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1447 | cancel_delayed_work(&hdev->discov_off); | 1422 | cancel_delayed_work(&hdev->discov_off); |
1448 | hdev->discov_timeout = timeout; | 1423 | hdev->discov_timeout = timeout; |
1449 | 1424 | ||
1425 | if (cp->val) | ||
1426 | hci_dev_set_flag(hdev, HCI_DISCOVERABLE); | ||
1427 | else | ||
1428 | hci_dev_clear_flag(hdev, HCI_DISCOVERABLE); | ||
1429 | |||
1450 | /* Limited discoverable mode */ | 1430 | /* Limited discoverable mode */ |
1451 | if (cp->val == 0x02) | 1431 | if (cp->val == 0x02) |
1452 | hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE); | 1432 | hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE); |
1453 | else | 1433 | else |
1454 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); | 1434 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); |
1455 | 1435 | ||
1456 | hci_req_init(&req, hdev); | 1436 | queue_work(hdev->req_workqueue, &hdev->discoverable_update); |
1457 | 1437 | err = 0; | |
1458 | /* The procedure for LE-only controllers is much simpler - just | ||
1459 | * update the advertising data. | ||
1460 | */ | ||
1461 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | ||
1462 | goto update_ad; | ||
1463 | |||
1464 | scan = SCAN_PAGE; | ||
1465 | |||
1466 | if (cp->val) { | ||
1467 | struct hci_cp_write_current_iac_lap hci_cp; | ||
1468 | |||
1469 | if (cp->val == 0x02) { | ||
1470 | /* Limited discoverable mode */ | ||
1471 | hci_cp.num_iac = min_t(u8, hdev->num_iac, 2); | ||
1472 | hci_cp.iac_lap[0] = 0x00; /* LIAC */ | ||
1473 | hci_cp.iac_lap[1] = 0x8b; | ||
1474 | hci_cp.iac_lap[2] = 0x9e; | ||
1475 | hci_cp.iac_lap[3] = 0x33; /* GIAC */ | ||
1476 | hci_cp.iac_lap[4] = 0x8b; | ||
1477 | hci_cp.iac_lap[5] = 0x9e; | ||
1478 | } else { | ||
1479 | /* General discoverable mode */ | ||
1480 | hci_cp.num_iac = 1; | ||
1481 | hci_cp.iac_lap[0] = 0x33; /* GIAC */ | ||
1482 | hci_cp.iac_lap[1] = 0x8b; | ||
1483 | hci_cp.iac_lap[2] = 0x9e; | ||
1484 | } | ||
1485 | |||
1486 | hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP, | ||
1487 | (hci_cp.num_iac * 3) + 1, &hci_cp); | ||
1488 | |||
1489 | scan |= SCAN_INQUIRY; | ||
1490 | } else { | ||
1491 | hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); | ||
1492 | } | ||
1493 | |||
1494 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan); | ||
1495 | |||
1496 | update_ad: | ||
1497 | __hci_req_update_adv_data(&req, HCI_ADV_CURRENT); | ||
1498 | |||
1499 | err = hci_req_run(&req, set_discoverable_complete); | ||
1500 | if (err < 0) | ||
1501 | mgmt_pending_remove(cmd); | ||
1502 | 1438 | ||
1503 | failed: | 1439 | failed: |
1504 | hci_dev_unlock(hdev); | 1440 | hci_dev_unlock(hdev); |