aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2013-03-15 18:07:05 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-03-18 13:02:06 -0400
commit33e38b3e13e313baedd7c56c38ad249f230171d2 (patch)
tree7070d4527786b5bd158bf5f96ddb74bc7fd026c7
parent2b76f4539c6a41c3dd2e73f9ca7e03bcff6c8774 (diff)
Bluetooth: Fix fast connectable response sending
The mgmt_set_fast_connectable response should be sent only when all related HCI commands have completed. This patch fixes the issue by using an async request and sending the response to user space throught the complete callback of the request. The patch also fixes in the same go the return parameters of the command which should be the current settings. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
-rw-r--r--net/bluetooth/mgmt.c53
1 files changed, 42 insertions, 11 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index a4f928ddc28a..bd61318b647c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2896,11 +2896,39 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
2896 return err; 2896 return err;
2897} 2897}
2898 2898
2899static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
2900{
2901 struct pending_cmd *cmd;
2902
2903 BT_DBG("status 0x%02x", status);
2904
2905 hci_dev_lock(hdev);
2906
2907 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
2908 if (!cmd)
2909 goto unlock;
2910
2911 if (status) {
2912 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
2913 mgmt_status(status));
2914 } else {
2915 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
2916 new_settings(hdev, cmd->sk);
2917 }
2918
2919 mgmt_pending_remove(cmd);
2920
2921unlock:
2922 hci_dev_unlock(hdev);
2923}
2924
2899static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, 2925static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
2900 void *data, u16 len) 2926 void *data, u16 len)
2901{ 2927{
2902 struct mgmt_mode *cp = data; 2928 struct mgmt_mode *cp = data;
2903 struct hci_cp_write_page_scan_activity acp; 2929 struct hci_cp_write_page_scan_activity acp;
2930 struct pending_cmd *cmd;
2931 struct hci_request req;
2904 u8 type; 2932 u8 type;
2905 int err; 2933 int err;
2906 2934
@@ -2939,25 +2967,28 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
2939 /* default 11.25 msec page scan window */ 2967 /* default 11.25 msec page scan window */
2940 acp.window = __constant_cpu_to_le16(0x0012); 2968 acp.window = __constant_cpu_to_le16(0x0012);
2941 2969
2942 err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), 2970 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
2943 &acp); 2971 data, len);
2944 if (err < 0) { 2972 if (!cmd) {
2945 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, 2973 err = -ENOMEM;
2946 MGMT_STATUS_FAILED); 2974 goto unlock;
2947 goto done;
2948 } 2975 }
2949 2976
2950 err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); 2977 hci_req_init(&req, hdev);
2978
2979 hci_req_add(&req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), &acp);
2980 hci_req_add(&req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
2981
2982 err = hci_req_run(&req, fast_connectable_complete);
2951 if (err < 0) { 2983 if (err < 0) {
2952 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, 2984 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
2953 MGMT_STATUS_FAILED); 2985 MGMT_STATUS_FAILED);
2954 goto done; 2986 mgmt_pending_remove(cmd);
2955 } 2987 }
2956 2988
2957 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, 0, 2989unlock:
2958 NULL, 0);
2959done:
2960 hci_dev_unlock(hdev); 2990 hci_dev_unlock(hdev);
2991
2961 return err; 2992 return err;
2962} 2993}
2963 2994