Re: [PATCH v3 08/13] Bluetooth: Implement MSFT avdtp open command

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Kiran,

On Sun, Nov 14, 2021 at 10:44 PM Kiran K <kiran.k@xxxxxxxxx> wrote:
>
> In A2DP offload use case, controller needs to configured
> with selected codec capabilities, dcid of media transport
> channel and ACL connection handle.
>
> Controller responds with avdtp handle which needs to be
> sent in other avdtp commands like start, suspend and close.
>
> Signed-off-by: Kiran K <kiran.k@xxxxxxxxx>
> Reviewed-by: Chethan T N <chethan.tumkur.narayan@xxxxxxxxx>
> Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@xxxxxxxxx>
> ---
>  include/net/bluetooth/bluetooth.h |  2 ++
>  include/net/bluetooth/hci.h       | 16 ++++++++++++
>  net/bluetooth/hci_codec.c         | 43 +++++++++++++++++++++++++++++++
>  net/bluetooth/hci_codec.h         |  4 +++
>  net/bluetooth/l2cap_sock.c        | 24 +++++++++++++++++
>  5 files changed, 89 insertions(+)
>
> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> index 2f31e571f34c..5e07cfed941d 100644
> --- a/include/net/bluetooth/bluetooth.h
> +++ b/include/net/bluetooth/bluetooth.h
> @@ -177,6 +177,8 @@ struct bt_codecs {
>  #define BT_CODEC_TRANSPARENT   0x03
>  #define BT_CODEC_MSBC          0x05
>
> +#define BT_MSFT_OPEN           20

I rather not have each command as a different sockopt, instead I would
suggest just one opcode and a internal header for each command so we
don't pollute too much our sockopt space since this only really apply
to MSFT I guess calling it BT_MSFT should be fine, also Id make it
extensible so we have a header and a flexible payload in case more
commands needs to be added.

>  __printf(1, 2)
>  void bt_info(const char *fmt, ...);
>  __printf(1, 2)
> diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
> index 7ea1bfce204f..a7dad0125c10 100644
> --- a/include/net/bluetooth/hci.h
> +++ b/include/net/bluetooth/hci.h
> @@ -2009,6 +2009,22 @@ struct hci_cp_le_reject_cis {
>         __u8    reason;
>  } __packed;
>
> +#define HCI_MSFT_AVDTP_CMD                     0xfc1e
> +
> +#define HCI_MSFT_AVDTP_OPEN                    0x08
> +struct hci_media_service_caps {
> +       __u8    category;
> +       __u8    len;
> +       __u8    data[0];
> +} __packed;
> +
> +struct msft_cp_avdtp_open {
> +       __u8    sub_opcode;
> +       __le16  handle;
> +       __le16  dcid;
> +       __le16  omtu;
> +} __packed;
> +
>  /* ---- HCI Events ---- */
>  #define HCI_EV_INQUIRY_COMPLETE                0x01
>
> diff --git a/net/bluetooth/hci_codec.c b/net/bluetooth/hci_codec.c
> index c6bd934dcf36..e179f3bfb494 100644
> --- a/net/bluetooth/hci_codec.c
> +++ b/net/bluetooth/hci_codec.c
> @@ -355,3 +355,46 @@ int hci_get_supported_codecs(struct hci_dev *hdev, u8 type, char __user *optval,
>  error:
>         return err;
>  }
> +
> +int hci_configure_msft_avdtp_open(struct hci_dev *hdev, struct l2cap_chan *chan,
> +                                 sockptr_t optval, int optlen)
> +{
> +       struct msft_cp_avdtp_open *cmd = NULL;
> +       struct hci_media_service_caps *caps;
> +       int err;
> +
> +       if (!optlen || optlen < sizeof(*caps)) {
> +               err = -EINVAL;
> +               goto fail;
> +       }
> +
> +       cmd = kzalloc(sizeof(*cmd) + optlen, GFP_KERNEL);
> +       if (!cmd) {
> +               err = -ENOMEM;
> +               goto fail;
> +       }
> +
> +       cmd->sub_opcode = HCI_MSFT_AVDTP_OPEN;
> +       cmd->handle = __cpu_to_le16(chan->conn->hcon->handle);
> +       cmd->dcid = cpu_to_le16(chan->dcid);
> +       cmd->omtu = cpu_to_le16(chan->omtu);
> +       caps = (void *)(cmd + 1);
> +
> +       if (copy_from_sockptr(caps, optval, optlen)) {
> +               err = -EFAULT;
> +               goto fail;
> +       }
> +
> +       if (caps->category != 0x07) {
> +               err = -EINVAL;
> +               goto fail;
> +       }
> +
> +       hci_send_cmd(hdev, HCI_MSFT_AVDTP_CMD, sizeof(*cmd) + optlen, cmd);
> +
> +       /* wait until we get avdtp handle or timeout */
> +
> +fail:
> +       kfree(cmd);
> +       return err;
> +}
> diff --git a/net/bluetooth/hci_codec.h b/net/bluetooth/hci_codec.h
> index 6e849c7d75b9..123b46a6a8ce 100644
> --- a/net/bluetooth/hci_codec.h
> +++ b/net/bluetooth/hci_codec.h
> @@ -2,8 +2,12 @@
>
>  /* Copyright (C) 2014 Intel Corporation */
>
> +#include <net/bluetooth/l2cap.h>
> +
>  void hci_read_supported_codecs(struct hci_dev *hdev);
>  void hci_read_supported_codecs_v2(struct hci_dev *hdev);
>  void hci_codec_list_clear(struct list_head *codec_list);
>  int hci_get_supported_codecs(struct hci_dev *hdev, u8 type, char __user *optval,
>                              int __user *optlen, int len);
> +int hci_configure_msft_avdtp_open(struct hci_dev *hdev, struct l2cap_chan *chan,
> +                                 sockptr_t optval, int optlen);

Id place this function inside msft.h/msft.c since this is a MSFT extension.

> diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> index a883acf33e3c..fa689e576576 100644
> --- a/net/bluetooth/l2cap_sock.c
> +++ b/net/bluetooth/l2cap_sock.c
> @@ -909,6 +909,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
>         struct l2cap_conn *conn;
>         int len, err = 0;
>         u32 opt;
> +       struct hci_dev *hdev;
>
>         BT_DBG("sk %p", sk);
>
> @@ -1137,6 +1138,29 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
>
>                 break;
>
> +       case BT_MSFT_OPEN:
> +               if (sk->sk_state != BT_CONNECTED) {
> +                       err = -ENOTCONN;
> +                       break;
> +               }
> +
> +               hdev = hci_get_route(BDADDR_ANY, &chan->src, BDADDR_BREDR);
> +               if (!hdev) {
> +                       err = -EBADFD;
> +                       break;
> +               }
> +
> +               if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED) ||
> +                   !hdev->get_data_path_id) {
> +                       err = -EOPNOTSUPP;
> +                       hci_dev_put(hdev);
> +                       break;
> +               }
> +
> +               err = hci_configure_msft_avdtp_open(hdev, chan, optval, optlen);
> +               hci_dev_put(hdev);
> +               break;
> +
>         default:
>                 err = -ENOPROTOOPT;
>                 break;
> --
> 2.17.1
>


-- 
Luiz Augusto von Dentz



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux