@@ -139,6 +139,12 @@ struct msft_cp_avdtp_suspend {
__le16 avdtp_handle;
} __packed;
+#define MSFT_OP_AVDTP_CLOSE 0x0B
+struct msft_cp_avdtp_close {
+ u8 sub_opcode;
+ __le16 avdtp_handle;
+} __packed;
+
static int __msft_add_monitor_pattern(struct hci_dev *hdev,
struct adv_monitor *monitor);
static int __msft_remove_monitor(struct hci_dev *hdev,
@@ -922,6 +928,21 @@ static int msft_avdtp_suspend(struct hci_dev *hdev, struct sock *sk)
return hci_send_cmd(hdev, MSFT_OP_AVDTP, sizeof(cmd), &cmd);
}
+static int msft_avdtp_close(struct hci_dev *hdev, struct sock *sk)
+{
+ struct msft_cp_avdtp_close cmd;
+
+ if (!bt_sk(sk)->avdtp_handle)
+ return -EBADFD;
+
+ cmd.sub_opcode = MSFT_OP_AVDTP_CLOSE;
+ cmd.avdtp_handle = cpu_to_le16(bt_sk(sk)->avdtp_handle);
+
+ bt_sk(sk)->avdtp_handle = 0;
+
+ return hci_send_cmd(hdev, MSFT_OP_AVDTP, sizeof(cmd), &cmd);
+}
+
int msft_avdtp_cmd(struct hci_dev *hdev, struct l2cap_chan *chan,
sockptr_t optval, int optlen,
struct sock *sk)
@@ -964,6 +985,10 @@ int msft_avdtp_cmd(struct hci_dev *hdev, struct l2cap_chan *chan,
err = msft_avdtp_suspend(hdev, sk);
break;
+ case MSFT_OP_AVDTP_CLOSE:
+ err = msft_avdtp_close(hdev, sk);
+ break;
+
default:
err = -EINVAL;
bt_dev_err(hdev, "Invalid MSFT avdtp sub opcode = 0x%2.2x",
@@ -1023,6 +1048,7 @@ void msft_cc_avdtp(struct hci_dev *hdev, struct sk_buff *skb)
case MSFT_OP_AVDTP_START:
case MSFT_OP_AVDTP_SUSPEND:
+ case MSFT_OP_AVDTP_CLOSE:
break;
default: