aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2012-02-23 15:54:38 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2012-02-23 17:15:26 -0500
commitc95f0ba76f902bc8b540468b695bcfe8948e8e46 (patch)
treec5de0fe26773c40cf93cecca7554af859ecb2601
parent08c79b6133b70a6e3d462d11a89c80259ac66ec7 (diff)
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>
-rw-r--r--include/net/bluetooth/hci.h1
-rw-r--r--net/bluetooth/mgmt.c29
2 files changed, 28 insertions, 2 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index c97cf0872ac9..05bd9aca4054 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -100,6 +100,7 @@ enum {
100 HCI_CONNECTABLE, 100 HCI_CONNECTABLE,
101 HCI_DISCOVERABLE, 101 HCI_DISCOVERABLE,
102 HCI_LINK_SECURITY, 102 HCI_LINK_SECURITY,
103 HCI_PENDING_CLASS,
103}; 104};
104 105
105/* HCI ioctl defines */ 106/* HCI ioctl defines */
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 79fe57573463..9f912dc71bae 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -570,6 +570,7 @@ static u8 get_service_classes(struct hci_dev *hdev)
570static int update_class(struct hci_dev *hdev) 570static int update_class(struct hci_dev *hdev)
571{ 571{
572 u8 cod[3]; 572 u8 cod[3];
573 int err;
573 574
574 BT_DBG("%s", hdev->name); 575 BT_DBG("%s", hdev->name);
575 576
@@ -586,7 +587,11 @@ static int update_class(struct hci_dev *hdev)
586 if (memcmp(cod, hdev->dev_class, 3) == 0) 587 if (memcmp(cod, hdev->dev_class, 3) == 0)
587 return 0; 588 return 0;
588 589
589 return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); 590 err = hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
591 if (err == 0)
592 set_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
593
594 return err;
590} 595}
591 596
592static void service_cache_off(struct work_struct *work) 597static 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)
1344 1349
1345 hci_dev_lock(hdev); 1350 hci_dev_lock(hdev);
1346 1351
1352 if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
1353 err = cmd_status(sk, index, MGMT_OP_ADD_UUID,
1354 MGMT_STATUS_BUSY);
1355 goto failed;
1356 }
1357
1347 uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC); 1358 uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
1348 if (!uuid) { 1359 if (!uuid) {
1349 err = -ENOMEM; 1360 err = -ENOMEM;
@@ -1393,6 +1404,12 @@ static int remove_uuid(struct sock *sk, u16 index, void *data, u16 len)
1393 1404
1394 hci_dev_lock(hdev); 1405 hci_dev_lock(hdev);
1395 1406
1407 if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
1408 err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
1409 MGMT_STATUS_BUSY);
1410 goto unlock;
1411 }
1412
1396 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) { 1413 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
1397 err = hci_uuids_clear(hdev); 1414 err = hci_uuids_clear(hdev);
1398 1415
@@ -1460,6 +1477,12 @@ static int set_dev_class(struct sock *sk, u16 index, void *data, u16 len)
1460 1477
1461 hci_dev_lock(hdev); 1478 hci_dev_lock(hdev);
1462 1479
1480 if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
1481 err = cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
1482 MGMT_STATUS_BUSY);
1483 goto unlock;
1484 }
1485
1463 hdev->major_class = cp->major; 1486 hdev->major_class = cp->major;
1464 hdev->minor_class = cp->minor; 1487 hdev->minor_class = cp->minor;
1465 1488
@@ -3259,7 +3282,7 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
3259 bacpy(&ev->addr.bdaddr, bdaddr); 3282 bacpy(&ev->addr.bdaddr, bdaddr);
3260 ev->addr.type = link_to_mgmt(link_type, addr_type); 3283 ev->addr.type = link_to_mgmt(link_type, addr_type);
3261 3284
3262 put_unaligned_le32(flags, &ev->flags); 3285 ev->flags = __cpu_to_le32(flags);
3263 3286
3264 if (name_len > 0) 3287 if (name_len > 0)
3265 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, 3288 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,
3614{ 3637{
3615 int err; 3638 int err;
3616 3639
3640 clear_bit(HCI_PENDING_CLASS, &hdev->dev_flags);
3641
3617 err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3, NULL); 3642 err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3, NULL);
3618 3643
3619 return err; 3644 return err;