diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2015-11-22 12:00:22 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-12-09 18:51:48 -0500 |
commit | 14bf5eac7a4f4bf0729ff8eb358de4fab967cee1 (patch) | |
tree | 82a17c6b076ce7a7f496833f36cb1f267fc14faa /net/bluetooth | |
parent | 53c0ba74510c1182786dcd1e3710215467777601 (diff) |
Bluetooth: Perform Class of Device changes through hdev->req_workqueue
The Class of Device needs to be changed e.g. for limited discoverable
mode. In preparation of moving the discoverable mode to hci_request.c
and hdev->req_workqueue, move the Class of Device helpers there first.
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 | 40 | ||||
-rw-r--r-- | net/bluetooth/hci_request.h | 2 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 54 |
3 files changed, 49 insertions, 47 deletions
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 167c90644b4b..e5e827b762b9 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c | |||
@@ -1311,6 +1311,46 @@ static void connectable_update_work(struct work_struct *work) | |||
1311 | mgmt_set_connectable_complete(hdev, status); | 1311 | mgmt_set_connectable_complete(hdev, status); |
1312 | } | 1312 | } |
1313 | 1313 | ||
1314 | static u8 get_service_classes(struct hci_dev *hdev) | ||
1315 | { | ||
1316 | struct bt_uuid *uuid; | ||
1317 | u8 val = 0; | ||
1318 | |||
1319 | list_for_each_entry(uuid, &hdev->uuids, list) | ||
1320 | val |= uuid->svc_hint; | ||
1321 | |||
1322 | return val; | ||
1323 | } | ||
1324 | |||
1325 | void __hci_req_update_class(struct hci_request *req) | ||
1326 | { | ||
1327 | struct hci_dev *hdev = req->hdev; | ||
1328 | u8 cod[3]; | ||
1329 | |||
1330 | BT_DBG("%s", hdev->name); | ||
1331 | |||
1332 | if (!hdev_is_powered(hdev)) | ||
1333 | return; | ||
1334 | |||
1335 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | ||
1336 | return; | ||
1337 | |||
1338 | if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE)) | ||
1339 | return; | ||
1340 | |||
1341 | cod[0] = hdev->minor_class; | ||
1342 | cod[1] = hdev->major_class; | ||
1343 | cod[2] = get_service_classes(hdev); | ||
1344 | |||
1345 | if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE)) | ||
1346 | cod[1] |= 0x20; | ||
1347 | |||
1348 | if (memcmp(cod, hdev->dev_class, 3) == 0) | ||
1349 | return; | ||
1350 | |||
1351 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); | ||
1352 | } | ||
1353 | |||
1314 | void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn, | 1354 | void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn, |
1315 | u8 reason) | 1355 | u8 reason) |
1316 | { | 1356 | { |
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h index 5358b1b12ca0..41920348d68b 100644 --- a/net/bluetooth/hci_request.h +++ b/net/bluetooth/hci_request.h | |||
@@ -72,6 +72,8 @@ int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance, | |||
72 | void hci_req_clear_adv_instance(struct hci_dev *hdev, struct hci_request *req, | 72 | void hci_req_clear_adv_instance(struct hci_dev *hdev, struct hci_request *req, |
73 | u8 instance, bool force); | 73 | u8 instance, bool force); |
74 | 74 | ||
75 | void __hci_req_update_class(struct hci_request *req); | ||
76 | |||
75 | /* Returns true if HCI commands were queued */ | 77 | /* Returns true if HCI commands were queued */ |
76 | bool hci_req_stop_discovery(struct hci_request *req); | 78 | bool hci_req_stop_discovery(struct hci_request *req); |
77 | 79 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index d8b76ca5c820..f5a4ee92f2bf 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -959,46 +959,6 @@ static void update_eir(struct hci_request *req) | |||
959 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | 959 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); |
960 | } | 960 | } |
961 | 961 | ||
962 | static u8 get_service_classes(struct hci_dev *hdev) | ||
963 | { | ||
964 | struct bt_uuid *uuid; | ||
965 | u8 val = 0; | ||
966 | |||
967 | list_for_each_entry(uuid, &hdev->uuids, list) | ||
968 | val |= uuid->svc_hint; | ||
969 | |||
970 | return val; | ||
971 | } | ||
972 | |||
973 | static void update_class(struct hci_request *req) | ||
974 | { | ||
975 | struct hci_dev *hdev = req->hdev; | ||
976 | u8 cod[3]; | ||
977 | |||
978 | BT_DBG("%s", hdev->name); | ||
979 | |||
980 | if (!hdev_is_powered(hdev)) | ||
981 | return; | ||
982 | |||
983 | if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) | ||
984 | return; | ||
985 | |||
986 | if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE)) | ||
987 | return; | ||
988 | |||
989 | cod[0] = hdev->minor_class; | ||
990 | cod[1] = hdev->major_class; | ||
991 | cod[2] = get_service_classes(hdev); | ||
992 | |||
993 | if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE)) | ||
994 | cod[1] |= 0x20; | ||
995 | |||
996 | if (memcmp(cod, hdev->dev_class, 3) == 0) | ||
997 | return; | ||
998 | |||
999 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); | ||
1000 | } | ||
1001 | |||
1002 | static void service_cache_off(struct work_struct *work) | 962 | static void service_cache_off(struct work_struct *work) |
1003 | { | 963 | { |
1004 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 964 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
@@ -1013,7 +973,7 @@ static void service_cache_off(struct work_struct *work) | |||
1013 | hci_dev_lock(hdev); | 973 | hci_dev_lock(hdev); |
1014 | 974 | ||
1015 | update_eir(&req); | 975 | update_eir(&req); |
1016 | update_class(&req); | 976 | __hci_req_update_class(&req); |
1017 | 977 | ||
1018 | hci_dev_unlock(hdev); | 978 | hci_dev_unlock(hdev); |
1019 | 979 | ||
@@ -1370,7 +1330,7 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status, | |||
1370 | */ | 1330 | */ |
1371 | hci_req_init(&req, hdev); | 1331 | hci_req_init(&req, hdev); |
1372 | __hci_req_update_scan(&req); | 1332 | __hci_req_update_scan(&req); |
1373 | update_class(&req); | 1333 | __hci_req_update_class(&req); |
1374 | hci_req_run(&req, NULL); | 1334 | hci_req_run(&req, NULL); |
1375 | 1335 | ||
1376 | remove_cmd: | 1336 | remove_cmd: |
@@ -2177,7 +2137,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
2177 | 2137 | ||
2178 | hci_req_init(&req, hdev); | 2138 | hci_req_init(&req, hdev); |
2179 | 2139 | ||
2180 | update_class(&req); | 2140 | __hci_req_update_class(&req); |
2181 | update_eir(&req); | 2141 | update_eir(&req); |
2182 | 2142 | ||
2183 | err = hci_req_run(&req, add_uuid_complete); | 2143 | err = hci_req_run(&req, add_uuid_complete); |
@@ -2277,7 +2237,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2277 | update_class: | 2237 | update_class: |
2278 | hci_req_init(&req, hdev); | 2238 | hci_req_init(&req, hdev); |
2279 | 2239 | ||
2280 | update_class(&req); | 2240 | __hci_req_update_class(&req); |
2281 | update_eir(&req); | 2241 | update_eir(&req); |
2282 | 2242 | ||
2283 | err = hci_req_run(&req, remove_uuid_complete); | 2243 | err = hci_req_run(&req, remove_uuid_complete); |
@@ -2356,7 +2316,7 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2356 | update_eir(&req); | 2316 | update_eir(&req); |
2357 | } | 2317 | } |
2358 | 2318 | ||
2359 | update_class(&req); | 2319 | __hci_req_update_class(&req); |
2360 | 2320 | ||
2361 | err = hci_req_run(&req, set_class_complete); | 2321 | err = hci_req_run(&req, set_class_complete); |
2362 | if (err < 0) { | 2322 | if (err < 0) { |
@@ -6871,7 +6831,7 @@ static int powered_update_hci(struct hci_dev *hdev) | |||
6871 | else | 6831 | else |
6872 | write_fast_connectable(&req, false); | 6832 | write_fast_connectable(&req, false); |
6873 | __hci_req_update_scan(&req); | 6833 | __hci_req_update_scan(&req); |
6874 | update_class(&req); | 6834 | __hci_req_update_class(&req); |
6875 | update_name(&req); | 6835 | update_name(&req); |
6876 | update_eir(&req); | 6836 | update_eir(&req); |
6877 | } | 6837 | } |
@@ -6972,7 +6932,7 @@ void mgmt_discoverable_timeout(struct hci_dev *hdev) | |||
6972 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, | 6932 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, |
6973 | sizeof(scan), &scan); | 6933 | sizeof(scan), &scan); |
6974 | } | 6934 | } |
6975 | update_class(&req); | 6935 | __hci_req_update_class(&req); |
6976 | 6936 | ||
6977 | /* Advertising instances don't use the global discoverable setting, so | 6937 | /* Advertising instances don't use the global discoverable setting, so |
6978 | * only update AD if advertising was enabled using Set Advertising. | 6938 | * only update AD if advertising was enabled using Set Advertising. |