summaryrefslogtreecommitdiff
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2012-02-02 04:02:29 +0200
committerJohan Hedberg <johan.hedberg@intel.com>2012-02-13 17:01:32 +0200
commit28424707a2e4ad38ab546d2ed5e3d6b035a84258 (patch)
tree60fd8524c956047add2055b350dc600f3d24ff36 /net/bluetooth/mgmt.c
parent95947a391ebe685b9870cd25cac1433aedf5d49c (diff)
downloadlwn-28424707a2e4ad38ab546d2ed5e3d6b035a84258.tar.gz
lwn-28424707a2e4ad38ab546d2ed5e3d6b035a84258.zip
Bluetooth: mgmt: Implement Cancel Pair Device command
This patch implements the Cancel Pair Device command for mgmt. It's used by user space to cancel an ongoing pairing attempt which was triggered by the Pair Device command. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r--net/bluetooth/mgmt.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 89707996d352..00ab083749eb 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1594,6 +1594,54 @@ unlock:
return err;
}
+static int cancel_pair_device(struct sock *sk, u16 index,
+ unsigned char *data, u16 len)
+{
+ struct mgmt_addr_info *addr = (void *) data;
+ struct hci_dev *hdev;
+ struct pending_cmd *cmd;
+ struct hci_conn *conn;
+ int err;
+
+ BT_DBG("");
+
+ if (len != sizeof(*addr))
+ return cmd_status(sk, index, MGMT_OP_CANCEL_PAIR_DEVICE,
+ MGMT_STATUS_INVALID_PARAMS);
+
+ hdev = hci_dev_get(index);
+ if (!hdev)
+ return cmd_status(sk, index, MGMT_OP_CANCEL_PAIR_DEVICE,
+ MGMT_STATUS_INVALID_PARAMS);
+
+ hci_dev_lock(hdev);
+
+ cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
+ if (!cmd) {
+ err = cmd_status(sk, index, MGMT_OP_CANCEL_PAIR_DEVICE,
+ MGMT_STATUS_INVALID_PARAMS);
+ goto unlock;
+ }
+
+ conn = cmd->user_data;
+
+ if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
+ err = cmd_status(sk, index, MGMT_OP_CANCEL_PAIR_DEVICE,
+ MGMT_STATUS_INVALID_PARAMS);
+ goto unlock;
+ }
+
+ pairing_complete(cmd, MGMT_STATUS_CANCELLED);
+
+ err = cmd_complete(sk, index, MGMT_OP_CANCEL_PAIR_DEVICE, addr,
+ sizeof(*addr));
+unlock:
+ hci_dev_unlock(hdev);
+ hci_dev_put(hdev);
+
+ return err;
+}
+
static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
u16 mgmt_op, u16 hci_op, __le32 passkey)
{
@@ -2271,6 +2319,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
case MGMT_OP_PAIR_DEVICE:
err = pair_device(sk, index, buf + sizeof(*hdr), len);
break;
+ case MGMT_OP_CANCEL_PAIR_DEVICE:
+ err = cancel_pair_device(sk, index, buf + sizeof(*hdr), len);
+ break;
case MGMT_OP_USER_CONFIRM_REPLY:
err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len);
break;