summaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2015-11-22 12:00:22 -0500
committerMarcel Holtmann <marcel@holtmann.org>2015-12-09 18:51:48 -0500
commit14bf5eac7a4f4bf0729ff8eb358de4fab967cee1 (patch)
tree82a17c6b076ce7a7f496833f36cb1f267fc14faa /net/bluetooth
parent53c0ba74510c1182786dcd1e3710215467777601 (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.c40
-rw-r--r--net/bluetooth/hci_request.h2
-rw-r--r--net/bluetooth/mgmt.c54
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
1314static 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
1325void __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
1314void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn, 1354void __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,
72void hci_req_clear_adv_instance(struct hci_dev *hdev, struct hci_request *req, 72void 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
75void __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 */
76bool hci_req_stop_discovery(struct hci_request *req); 78bool 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
962static 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
973static 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
1002static void service_cache_off(struct work_struct *work) 962static 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
1376remove_cmd: 1336remove_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,
2277update_class: 2237update_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.