mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-11 23:50:25 +00:00
Bluetooth: mgmt: Track pending class changes
This patch adds a flag to track pending changes to the class of device. This is needed since we cannot cleanly handle multiple simultaneous commands and need to return a "busy" error status in the mgmt commands that might trigger a class change. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
08c79b6133
commit
c95f0ba76f
@ -100,6 +100,7 @@ enum {
|
|||||||
HCI_CONNECTABLE,
|
HCI_CONNECTABLE,
|
||||||
HCI_DISCOVERABLE,
|
HCI_DISCOVERABLE,
|
||||||
HCI_LINK_SECURITY,
|
HCI_LINK_SECURITY,
|
||||||
|
HCI_PENDING_CLASS,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* HCI ioctl defines */
|
/* HCI ioctl defines */
|
||||||
|
@ -570,6 +570,7 @@ static u8 get_service_classes(struct hci_dev *hdev)
|
|||||||
static int update_class(struct hci_dev *hdev)
|
static int update_class(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
u8 cod[3];
|
u8 cod[3];
|
||||||
|
int err;
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
@ -586,7 +587,11 @@ static int update_class(struct hci_dev *hdev)
|
|||||||
if (memcmp(cod, hdev->dev_class, 3) == 0)
|
if (memcmp(cod, hdev->dev_class, 3) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
|
err = hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
|
||||||
|
if (err == 0)
|
||||||
|
set_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void service_cache_off(struct work_struct *work)
|
static void service_cache_off(struct work_struct *work)
|
||||||
@ -1344,6 +1349,12 @@ static int add_uuid(struct sock *sk, u16 index, void *data, u16 len)
|
|||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
|
if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
|
||||||
|
err = cmd_status(sk, index, MGMT_OP_ADD_UUID,
|
||||||
|
MGMT_STATUS_BUSY);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
|
uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
|
||||||
if (!uuid) {
|
if (!uuid) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
@ -1393,6 +1404,12 @@ static int remove_uuid(struct sock *sk, u16 index, void *data, u16 len)
|
|||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
|
if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
|
||||||
|
err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
|
||||||
|
MGMT_STATUS_BUSY);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
|
if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
|
||||||
err = hci_uuids_clear(hdev);
|
err = hci_uuids_clear(hdev);
|
||||||
|
|
||||||
@ -1460,6 +1477,12 @@ static int set_dev_class(struct sock *sk, u16 index, void *data, u16 len)
|
|||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
|
if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
|
||||||
|
err = cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
|
||||||
|
MGMT_STATUS_BUSY);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
hdev->major_class = cp->major;
|
hdev->major_class = cp->major;
|
||||||
hdev->minor_class = cp->minor;
|
hdev->minor_class = cp->minor;
|
||||||
|
|
||||||
@ -3259,7 +3282,7 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|||||||
bacpy(&ev->addr.bdaddr, bdaddr);
|
bacpy(&ev->addr.bdaddr, bdaddr);
|
||||||
ev->addr.type = link_to_mgmt(link_type, addr_type);
|
ev->addr.type = link_to_mgmt(link_type, addr_type);
|
||||||
|
|
||||||
put_unaligned_le32(flags, &ev->flags);
|
ev->flags = __cpu_to_le32(flags);
|
||||||
|
|
||||||
if (name_len > 0)
|
if (name_len > 0)
|
||||||
eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
|
eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
|
||||||
@ -3614,6 +3637,8 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
clear_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
|
||||||
|
|
||||||
err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3, NULL);
|
err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3, NULL);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user