diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2013-03-15 18:07:05 -0400 |
---|---|---|
committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2013-03-18 13:02:06 -0400 |
commit | 33e38b3e13e313baedd7c56c38ad249f230171d2 (patch) | |
tree | 7070d4527786b5bd158bf5f96ddb74bc7fd026c7 /net/bluetooth | |
parent | 2b76f4539c6a41c3dd2e73f9ca7e03bcff6c8774 (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>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/mgmt.c | 53 |
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 | ||
2899 | static 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 | |||
2921 | unlock: | ||
2922 | hci_dev_unlock(hdev); | ||
2923 | } | ||
2924 | |||
2899 | static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, | 2925 | static 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, | 2989 | unlock: |
2958 | NULL, 0); | ||
2959 | done: | ||
2960 | hci_dev_unlock(hdev); | 2990 | hci_dev_unlock(hdev); |
2991 | |||
2961 | return err; | 2992 | return err; |
2962 | } | 2993 | } |
2963 | 2994 | ||