Skip to content

Commit

Permalink
Bluetooth: Perform Class of Device changes through hdev->req_workqueue
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Marcel Holtmann <[email protected]>
  • Loading branch information
Johan Hedberg authored and holtmann committed Dec 9, 2015
1 parent 53c0ba7 commit 14bf5ea
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 47 deletions.
40 changes: 40 additions & 0 deletions net/bluetooth/hci_request.c
Original file line number Diff line number Diff line change
Expand Up @@ -1311,6 +1311,46 @@ static void connectable_update_work(struct work_struct *work)
mgmt_set_connectable_complete(hdev, status);
}

static u8 get_service_classes(struct hci_dev *hdev)
{
struct bt_uuid *uuid;
u8 val = 0;

list_for_each_entry(uuid, &hdev->uuids, list)
val |= uuid->svc_hint;

return val;
}

void __hci_req_update_class(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
u8 cod[3];

BT_DBG("%s", hdev->name);

if (!hdev_is_powered(hdev))
return;

if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return;

if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
return;

cod[0] = hdev->minor_class;
cod[1] = hdev->major_class;
cod[2] = get_service_classes(hdev);

if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
cod[1] |= 0x20;

if (memcmp(cod, hdev->dev_class, 3) == 0)
return;

hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
}

void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn,
u8 reason)
{
Expand Down
2 changes: 2 additions & 0 deletions net/bluetooth/hci_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
void hci_req_clear_adv_instance(struct hci_dev *hdev, struct hci_request *req,
u8 instance, bool force);

void __hci_req_update_class(struct hci_request *req);

/* Returns true if HCI commands were queued */
bool hci_req_stop_discovery(struct hci_request *req);

Expand Down
54 changes: 7 additions & 47 deletions net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -959,46 +959,6 @@ static void update_eir(struct hci_request *req)
hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
}

static u8 get_service_classes(struct hci_dev *hdev)
{
struct bt_uuid *uuid;
u8 val = 0;

list_for_each_entry(uuid, &hdev->uuids, list)
val |= uuid->svc_hint;

return val;
}

static void update_class(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
u8 cod[3];

BT_DBG("%s", hdev->name);

if (!hdev_is_powered(hdev))
return;

if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return;

if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
return;

cod[0] = hdev->minor_class;
cod[1] = hdev->major_class;
cod[2] = get_service_classes(hdev);

if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
cod[1] |= 0x20;

if (memcmp(cod, hdev->dev_class, 3) == 0)
return;

hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
}

static void service_cache_off(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev,
Expand All @@ -1013,7 +973,7 @@ static void service_cache_off(struct work_struct *work)
hci_dev_lock(hdev);

update_eir(&req);
update_class(&req);
__hci_req_update_class(&req);

hci_dev_unlock(hdev);

Expand Down Expand Up @@ -1370,7 +1330,7 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
*/
hci_req_init(&req, hdev);
__hci_req_update_scan(&req);
update_class(&req);
__hci_req_update_class(&req);
hci_req_run(&req, NULL);

remove_cmd:
Expand Down Expand Up @@ -2177,7 +2137,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)

hci_req_init(&req, hdev);

update_class(&req);
__hci_req_update_class(&req);
update_eir(&req);

err = hci_req_run(&req, add_uuid_complete);
Expand Down Expand Up @@ -2277,7 +2237,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
update_class:
hci_req_init(&req, hdev);

update_class(&req);
__hci_req_update_class(&req);
update_eir(&req);

err = hci_req_run(&req, remove_uuid_complete);
Expand Down Expand Up @@ -2356,7 +2316,7 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
update_eir(&req);
}

update_class(&req);
__hci_req_update_class(&req);

err = hci_req_run(&req, set_class_complete);
if (err < 0) {
Expand Down Expand Up @@ -6871,7 +6831,7 @@ static int powered_update_hci(struct hci_dev *hdev)
else
write_fast_connectable(&req, false);
__hci_req_update_scan(&req);
update_class(&req);
__hci_req_update_class(&req);
update_name(&req);
update_eir(&req);
}
Expand Down Expand Up @@ -6972,7 +6932,7 @@ void mgmt_discoverable_timeout(struct hci_dev *hdev)
hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
sizeof(scan), &scan);
}
update_class(&req);
__hci_req_update_class(&req);

/* Advertising instances don't use the global discoverable setting, so
* only update AD if advertising was enabled using Set Advertising.
Expand Down

0 comments on commit 14bf5ea

Please sign in to comment.