From patchwork Tue Jun 8 12:24:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 12306691 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.0 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D8ECEC4743D for ; Tue, 8 Jun 2021 12:20:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BC4256128A for ; Tue, 8 Jun 2021 12:20:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232498AbhFHMWo (ORCPT ); Tue, 8 Jun 2021 08:22:44 -0400 Received: from mga04.intel.com ([192.55.52.120]:22776 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231993AbhFHMWo (ORCPT ); Tue, 8 Jun 2021 08:22:44 -0400 IronPort-SDR: qVOzFgIVdm64z9Bvjuadneoa/8aak0SvMktzrW3TQdoXV8etEUqpgyTvbVk9ipicIOYt5VIEzZ tPqS4WyZdvjA== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="202973543" X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="202973543" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 05:20:49 -0700 IronPort-SDR: nXzEtADPsgXEuH2KuS3TWYrWp5KIBzgjehw4MWNVgrRAVgqb6FyoZf4YqDwYrKBbXhTnMjyKEM qmfsDtALWVtg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="619283433" Received: from intel-lenovo-legion-y540-15irh-pg0.iind.intel.com ([10.224.186.95]) by orsmga005.jf.intel.com with ESMTP; 08 Jun 2021 05:20:47 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: Kiran K , Chethan T N , Srivatsa Ravishankar Subject: [PATCH v9 01/10] Bluetooth: enumerate local supported codec and cache details Date: Tue, 8 Jun 2021 17:54:46 +0530 Message-Id: <20210608122455.19583-1-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Move reading of supported local codecs into a separate init function, query codecs capabilities and cache the data Signed-off-by: Kiran K Signed-off-by: Chethan T N Signed-off-by: Srivatsa Ravishankar Reported-by: kernel test robot Reported-by: kernel test robot --- * changes in v9: - use shortname vnd instead of ven * changes in v8: - add comments - split __u8 codec_id[5] into {__u8 id; __le16 cid, vid } - address review comment related codec caps structure * changes in v7: - keep codec enumeration call in hci_init instead of having a separate function - Remove unused bitmasks defined for LE transports * changes in v6: - fix compiler warning reported for ARCH=arc * changes in v5: - fix review comments - move code used to read standard/vendor codecs caps into single function * changes in v4: - convert reading of codecs and codecs caps calls from async to sync * changes in v3 move codec enumeration into a new init function * changes in v2 add skb length check before accessing data include/net/bluetooth/hci.h | 41 +++++++ include/net/bluetooth/hci_core.h | 17 +++ net/bluetooth/hci_core.c | 199 ++++++++++++++++++++++++++++++- 3 files changed, 253 insertions(+), 4 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 2dc947341502..3eb723765669 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1307,6 +1307,28 @@ struct hci_rp_read_data_block_size { } __packed; #define HCI_OP_READ_LOCAL_CODECS 0x100b +struct hci_std_codecs { + __u8 num; + __u8 codec[]; +} __packed; + +struct hci_vnd_codec { + /* company id */ + __le16 cid; + /* vendor codec id */ + __le16 vid; +} __packed; + +struct hci_vnd_codecs { + __u8 num; + struct hci_vnd_codec codec[]; +} __packed; + +struct hci_rp_read_local_supported_codecs { + __u8 status; + struct hci_std_codecs std_codecs; + struct hci_vnd_codecs vnd_codecs; +} __packed; #define HCI_OP_READ_LOCAL_PAIRING_OPTS 0x100c struct hci_rp_read_local_pairing_opts { @@ -1315,6 +1337,25 @@ struct hci_rp_read_local_pairing_opts { __u8 max_key_size; } __packed; +#define HCI_OP_READ_LOCAL_CODEC_CAPS 0x100e +struct hci_op_read_local_codec_caps { + __u8 id; + __le16 cid; + __le16 vid; + __u8 transport; + __u8 direction; +} __packed; + +struct hci_codec_caps { + __u8 len; + __u8 data[]; +} __packed; + +struct hci_rp_read_local_codec_caps { + __u8 status; + __u8 num_caps; +} __packed; + #define HCI_OP_READ_PAGE_SCAN_ACTIVITY 0x0c1b struct hci_rp_read_page_scan_activity { __u8 status; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 212f46806ce7..3284044c3dd7 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -131,6 +131,17 @@ struct bdaddr_list { u8 bdaddr_type; }; +struct codec_list { + struct list_head list; + u8 id; + __le16 cid; + __le16 vid; + u8 transport; + u8 num_caps; + u32 len; + struct hci_codec_caps caps[]; +}; + struct bdaddr_list_with_irk { struct list_head list; bdaddr_t bdaddr; @@ -535,6 +546,7 @@ struct hci_dev { struct list_head pend_le_conns; struct list_head pend_le_reports; struct list_head blocked_keys; + struct list_head local_codecs; struct hci_dev_stats stat; @@ -1849,4 +1861,9 @@ void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr, #define SCO_AIRMODE_CVSD 0x0000 #define SCO_AIRMODE_TRANSP 0x0003 +#define LOCAL_CODEC_ACL_MASK BIT(0) +#define LOCAL_CODEC_SCO_MASK BIT(1) + +#define TRANSPORT_TYPE_MAX 0x04 + #endif /* __HCI_CORE_H */ diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 1eb7ffd0dd29..3f77ce1e9dd6 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -838,10 +838,6 @@ static int hci_init4_req(struct hci_request *req, unsigned long opt) if (hdev->commands[22] & 0x04) hci_set_event_mask_page_2(req); - /* Read local codec list if the HCI command is supported */ - if (hdev->commands[29] & 0x20) - hci_req_add(req, HCI_OP_READ_LOCAL_CODECS, 0, NULL); - /* Read local pairing options if the HCI command is supported */ if (hdev->commands[41] & 0x08) hci_req_add(req, HCI_OP_READ_LOCAL_PAIRING_OPTS, 0, NULL); @@ -907,6 +903,195 @@ static int hci_init4_req(struct hci_request *req, unsigned long opt) return 0; } +static int hci_codec_list_add(struct list_head *list, + struct hci_op_read_local_codec_caps *sent, + struct hci_rp_read_local_codec_caps *rp, + void *caps, + __u32 len) +{ + struct codec_list *entry; + + entry = kzalloc(sizeof(*entry) + len, GFP_KERNEL); + if (!entry) + return -ENOMEM; + + entry->id = sent->id; + if (sent->id == 0xFF) { + entry->cid = __le16_to_cpu(sent->cid); + entry->vid = __le16_to_cpu(sent->vid); + } + entry->transport = sent->transport; + entry->len = len; + entry->num_caps = rp->num_caps; + if (rp->num_caps) + memcpy(entry->caps, caps, len); + list_add(&entry->list, list); + + return 0; +} + +static void hci_codec_list_clear(struct list_head *codec_list) +{ + struct codec_list *c, *n; + + list_for_each_entry_safe(c, n, codec_list, list) { + list_del(&c->list); + kfree(c); + } +} + +static void hci_read_codec_capabilities(struct hci_dev *hdev, void *codec_id, + __u8 transport, bool is_vnd_codec) +{ + struct hci_op_read_local_codec_caps cmd; + __u8 i; + + memset(&cmd, 0, sizeof(cmd)); + + if (is_vnd_codec) { + struct hci_vnd_codec *vnd_codec; + + vnd_codec = codec_id; + cmd.id = 0xFF; + cmd.cid = vnd_codec->cid; + cmd.vid = vnd_codec->vid; + } else { + cmd.id = *(__u8 *)codec_id; + } + + cmd.direction = 0x00; + + for (i = 0; i < TRANSPORT_TYPE_MAX; i++) { + if (transport & BIT(i)) { + struct hci_rp_read_local_codec_caps *rp; + struct hci_codec_caps *caps; + struct sk_buff *skb; + __u8 j; + __u32 len; + + cmd.transport = i; + skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_CODEC_CAPS, + sizeof(cmd), &cmd, + HCI_CMD_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Failed to read codec capabilities (%ld)", + PTR_ERR(skb)); + continue; + } + + if (skb->len < sizeof(*rp)) + goto error; + + rp = (void *)skb->data; + + if (rp->status) + goto error; + + if (!rp->num_caps) { + len = 0; + /* this codec doesn't have capabilities */ + goto skip_caps_parse; + } + + skb_pull(skb, sizeof(*rp)); + + for (j = 0, len = 0; j < rp->num_caps; j++) { + caps = (void *)skb->data; + if (skb->len < sizeof(*caps)) + goto error; + if (skb->len < caps->len) + goto error; + len += sizeof(caps->len) + caps->len; + skb_pull(skb, sizeof(caps->len) + caps->len); + } + +skip_caps_parse: + hci_dev_lock(hdev); + hci_codec_list_add(&hdev->local_codecs, &cmd, rp, + (__u8 *)rp + sizeof(*rp), len); + hci_dev_unlock(hdev); +error: + kfree_skb(skb); + } + } +} + +static void hci_codec_list_parse(struct hci_dev *hdev, __u8 num_codecs, + void *codec_list, bool is_vnd_codec) +{ + __u8 i; + + for (i = 0; i < num_codecs; i++) { + if (!is_vnd_codec) { + struct hci_std_codecs *codecs = codec_list; + + hci_read_codec_capabilities(hdev, &codecs->codec[i], + LOCAL_CODEC_ACL_MASK, + is_vnd_codec); + } else { + struct hci_vnd_codecs *codecs = codec_list; + + hci_read_codec_capabilities(hdev, &codecs->codec[i], + LOCAL_CODEC_ACL_MASK, + is_vnd_codec); + } + } +} + +static void hci_read_supported_codecs(struct hci_dev *hdev) +{ + struct sk_buff *skb; + struct hci_rp_read_local_supported_codecs *rp; + struct hci_std_codecs *std_codecs; + struct hci_vnd_codecs *vnd_codecs; + + skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_CODECS, 0, NULL, + HCI_CMD_TIMEOUT); + + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Failed to read local supported codecs (%ld)", + PTR_ERR(skb)); + return; + } + + if (skb->len < sizeof(*rp)) + goto error; + + rp = (void *)skb->data; + + if (rp->status) + goto error; + + skb_pull(skb, sizeof(rp->status)); + + std_codecs = (void *)skb->data; + + /* validate codecs length before accessing */ + if (skb->len < flex_array_size(std_codecs, codec, std_codecs->num) + + sizeof(std_codecs->num)) + goto error; + + /* enumerate codec capabilities of standard codecs */ + hci_codec_list_parse(hdev, std_codecs->num, std_codecs, false); + + skb_pull(skb, flex_array_size(std_codecs, codec, std_codecs->num) + + sizeof(std_codecs->num)); + + vnd_codecs = (void *)skb->data; + + /* validate vendor codecs length before accessing */ + if (skb->len < + flex_array_size(vnd_codecs, codec, vnd_codecs->num) + + sizeof(vnd_codecs->num)) + goto error; + + /* enumerate vendor codec capabilities */ + hci_codec_list_parse(hdev, vnd_codecs->num, vnd_codecs, true); + +error: + kfree_skb(skb); +} + static int __hci_init(struct hci_dev *hdev) { int err; @@ -937,6 +1122,10 @@ static int __hci_init(struct hci_dev *hdev) if (err < 0) return err; + /* Read local codec list if the HCI command is supported */ + if (hdev->commands[29] & 0x20) + hci_read_supported_codecs(hdev); + /* This function is only called when the controller is actually in * configured state. When the controller is marked as unconfigured, * this initialization procedure is not run. @@ -1836,6 +2025,7 @@ int hci_dev_do_close(struct hci_dev *hdev) memset(hdev->eir, 0, sizeof(hdev->eir)); memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); bacpy(&hdev->random_addr, BDADDR_ANY); + hci_codec_list_clear(&hdev->local_codecs); hci_req_sync_unlock(hdev); @@ -3837,6 +4027,7 @@ struct hci_dev *hci_alloc_dev(void) INIT_LIST_HEAD(&hdev->conn_hash.list); INIT_LIST_HEAD(&hdev->adv_instances); INIT_LIST_HEAD(&hdev->blocked_keys); + INIT_LIST_HEAD(&hdev->local_codecs); INIT_WORK(&hdev->rx_work, hci_rx_work); INIT_WORK(&hdev->cmd_work, hci_cmd_work); From patchwork Tue Jun 8 12:24:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 12306693 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 24AC4C47082 for ; Tue, 8 Jun 2021 12:20:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 108AE61182 for ; Tue, 8 Jun 2021 12:20:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232525AbhFHMWp (ORCPT ); Tue, 8 Jun 2021 08:22:45 -0400 Received: from mga04.intel.com ([192.55.52.120]:22776 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232211AbhFHMWo (ORCPT ); Tue, 8 Jun 2021 08:22:44 -0400 IronPort-SDR: JthD/noqXinrOw896jaLStm/bmVNUoCsDkU8Ix0e7qT++Z/bRYwvCkC7fkFcJJhRwM1jJmKo5C rAeOXKaLDZtw== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="202973548" X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="202973548" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 05:20:51 -0700 IronPort-SDR: MhtHfzzhnXNTyHlmbMWnGWzgzkBH//2RjE5sxlZApNK6BrylTTZNSRJcoBp4oG+EHf65YSFygD 3oL3Vl5gSuVw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="619283439" Received: from intel-lenovo-legion-y540-15irh-pg0.iind.intel.com ([10.224.186.95]) by orsmga005.jf.intel.com with ESMTP; 08 Jun 2021 05:20:49 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: Kiran K , Chethan T N , Srivatsa Ravishankar Subject: [PATCH v9 02/10] Bluetooth: Add support for Read Local Supported Codecs V2 Date: Tue, 8 Jun 2021 17:54:47 +0530 Message-Id: <20210608122455.19583-2-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210608122455.19583-1-kiran.k@intel.com> References: <20210608122455.19583-1-kiran.k@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Use V2 version of read local supported command is controller supports snoop: > HCI Event: Command Complete (0x0e) plen 20 Read Local Supported Codecs V2 (0x04|0x000d) ncmd 1 Status: Success (0x00) Number of supported codecs: 7 Codec: u-law log (0x00) Logical Transport Type: 0x02 Codec supported over BR/EDR SCO and eSCO Codec: A-law log (0x01) Logical Transport Type: 0x02 Codec supported over BR/EDR SCO and eSCO Codec: CVSD (0x02) Logical Transport Type: 0x02 Codec supported over BR/EDR SCO and eSCO Codec: Transparent (0x03) Logical Transport Type: 0x02 Codec supported over BR/EDR SCO and eSCO Codec: Linear PCM (0x04) Logical Transport Type: 0x02 Codec supported over BR/EDR SCO and eSCO Codec: Reserved (0x08) Logical Transport Type: 0x03 Codec supported over BR/EDR ACL Codec supported over BR/EDR SCO and eSCO Codec: mSBC (0x05) Logical Transport Type: 0x03 Codec supported over BR/EDR ACL Codec supported over BR/EDR SCO and eSCO Number of vendor codecs: 0 ...... < HCI Command: Read Local Suppor.. (0x04|0x000e) plen 7 Codec: mSBC (0x05) Logical Transport Type: 0x00 Direction: Input (Host to Controller) (0x00) > HCI Event: Command Complete (0x0e) plen 12 Read Local Supported Codec Capabilities (0x04|0x000e) ncmd 1 Status: Success (0x00) Number of codec capabilities: 1 Capabilities #0: 00 00 11 15 02 33 Signed-off-by: Kiran K Signed-off-by: Chethan T N Signed-off-by: Srivatsa Ravishankar --- * changes in v9: use vnd as shortcut name for vendor instead of ven * changes in v8: no changes * changes in v7: call codec enumeration code in hci_init instead of having it in a separate function * changes in v6 no changes * changes in v5: fix review comments * changes in v4: converts codec read capabilities calls from async to sync * changes in v3: No changes * changes in v2: add length check for event data before accessing include/net/bluetooth/hci.h | 29 ++++++++++++++ net/bluetooth/hci_core.c | 78 ++++++++++++++++++++++++++++++++++++- 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 3eb723765669..45bd9af4ce61 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1337,6 +1337,35 @@ struct hci_rp_read_local_pairing_opts { __u8 max_key_size; } __packed; +#define HCI_OP_READ_LOCAL_CODECS_V2 0x100d +struct hci_std_codec_v2 { + __u8 id; + __u8 transport; +} __packed; + +struct hci_std_codecs_v2 { + __u8 num; + struct hci_std_codec_v2 codec[]; +} __packed; + +struct hci_vnd_codec_v2 { + __u8 id; + __le16 cid; + __le16 vid; + __u8 transport; +} __packed; + +struct hci_vnd_codecs_v2 { + __u8 num; + struct hci_vnd_codec_v2 codec[]; +} __packed; + +struct hci_rp_read_local_supported_codecs_v2 { + __u8 status; + struct hci_std_codecs_v2 std_codecs; + struct hci_vnd_codecs_v2 vendor_codecs; +} __packed; + #define HCI_OP_READ_LOCAL_CODEC_CAPS 0x100e struct hci_op_read_local_codec_caps { __u8 id; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 3f77ce1e9dd6..186b347ae9d3 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1038,6 +1038,28 @@ static void hci_codec_list_parse(struct hci_dev *hdev, __u8 num_codecs, } } +static void hci_codec_list_parse_v2(struct hci_dev *hdev, __u8 num_codecs, + void *codec_list, bool is_vnd_codec) +{ + __u8 i; + + for (i = 0; i < num_codecs; i++) { + if (!is_vnd_codec) { + struct hci_std_codecs_v2 *codecs = codec_list; + + hci_read_codec_capabilities(hdev, &codecs->codec[i], + codecs->codec[i].transport, + is_vnd_codec); + } else { + struct hci_vnd_codecs_v2 *codecs = codec_list; + + hci_read_codec_capabilities(hdev, &codecs->codec[i], + codecs->codec[i].transport, + is_vnd_codec); + } + } +} + static void hci_read_supported_codecs(struct hci_dev *hdev) { struct sk_buff *skb; @@ -1092,6 +1114,58 @@ static void hci_read_supported_codecs(struct hci_dev *hdev) kfree_skb(skb); } +static void hci_read_supported_codecs_v2(struct hci_dev *hdev) +{ + struct sk_buff *skb; + struct hci_rp_read_local_supported_codecs_v2 *rp; + struct hci_std_codecs_v2 *std_codecs; + struct hci_vnd_codecs_v2 *vnd_codecs; + + skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_CODECS_V2, 0, NULL, + HCI_CMD_TIMEOUT); + + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Failed to read local supported codecs (%ld)", + PTR_ERR(skb)); + return; + } + + if (skb->len < sizeof(*rp)) + goto error; + + rp = (void *)skb->data; + + if (rp->status) + goto error; + + skb_pull(skb, sizeof(rp->status)); + + std_codecs = (void *)skb->data; + + /* check for payload data length before accessing */ + if (skb->len < flex_array_size(std_codecs, codec, std_codecs->num) + + sizeof(std_codecs->num)) + goto error; + + hci_codec_list_parse_v2(hdev, std_codecs->num, std_codecs, false); + + skb_pull(skb, flex_array_size(std_codecs, codec, std_codecs->num) + + sizeof(std_codecs->num)); + + vnd_codecs = (void *)skb->data; + + /* check for payload data length before accessing */ + if (skb->len < + flex_array_size(vnd_codecs, codec, vnd_codecs->num) + + sizeof(vnd_codecs->num)) + goto error; + + hci_codec_list_parse_v2(hdev, vnd_codecs->num, vnd_codecs, true); + +error: + kfree_skb(skb); +} + static int __hci_init(struct hci_dev *hdev) { int err; @@ -1123,7 +1197,9 @@ static int __hci_init(struct hci_dev *hdev) return err; /* Read local codec list if the HCI command is supported */ - if (hdev->commands[29] & 0x20) + if (hdev->commands[45] & 0x04) + hci_read_supported_codecs_v2(hdev); + else if (hdev->commands[29] & 0x20) hci_read_supported_codecs(hdev); /* This function is only called when the controller is actually in From patchwork Tue Jun 8 12:24:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 12306695 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05C86C48BCF for ; Tue, 8 Jun 2021 12:20:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E595061182 for ; Tue, 8 Jun 2021 12:20:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232531AbhFHMWp (ORCPT ); Tue, 8 Jun 2021 08:22:45 -0400 Received: from mga04.intel.com ([192.55.52.120]:22776 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231993AbhFHMWo (ORCPT ); Tue, 8 Jun 2021 08:22:44 -0400 IronPort-SDR: 0uhM40vYpIxkEUCkBqbiOrn5Dd7y5TV4qmKgzyBLVfyYpoxuodpUuBtyd3RYQYYc2iTtyXSKLL 1mPLHsftXKXA== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="202973550" X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="202973550" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 05:20:52 -0700 IronPort-SDR: 98a9bH3UBc2H3wdafjVxU4zFn6eR+wXFeyGjILQwAMWuXBYV8RmBuBS2LGWAj/1ibyK7lPNi7+ f349IGVX1Pqg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="619283444" Received: from intel-lenovo-legion-y540-15irh-pg0.iind.intel.com ([10.224.186.95]) by orsmga005.jf.intel.com with ESMTP; 08 Jun 2021 05:20:51 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: Kiran K Subject: [PATCH v9 03/10] Bluetooth: Add a callback function to retireve data path Date: Tue, 8 Jun 2021 17:54:48 +0530 Message-Id: <20210608122455.19583-3-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210608122455.19583-1-kiran.k@intel.com> References: <20210608122455.19583-1-kiran.k@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org There is no standard HCI command to retrieve data path for transport. Add a new callback function to retrieve data path which is used in offload usecase. This needs to be set at setup stage if controller supports offload codecs Signed-off-by: Kiran K Reviewed-by: Chethan T N Reviewed-by: Srivatsa Ravishankar --- * changes in v9: - define a separate patch for core changes include/net/bluetooth/hci_core.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3284044c3dd7..641477396da3 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -617,6 +617,7 @@ struct hci_dev { int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr); void (*cmd_timeout)(struct hci_dev *hdev); bool (*prevent_wake)(struct hci_dev *hdev); + int (*get_data_path)(struct hci_dev *hdev); }; #define HCI_PHY_HANDLE(handle) (handle & 0xff) From patchwork Tue Jun 8 12:24:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 12306697 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0E6ABC4743D for ; Tue, 8 Jun 2021 12:20:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EC49B61359 for ; Tue, 8 Jun 2021 12:20:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232541AbhFHMWq (ORCPT ); Tue, 8 Jun 2021 08:22:46 -0400 Received: from mga04.intel.com ([192.55.52.120]:22776 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232539AbhFHMWq (ORCPT ); Tue, 8 Jun 2021 08:22:46 -0400 IronPort-SDR: zmNMonpd4lLnFJ1GxX6nJgqUCaQAx2DgwCo1woVyFXlXHwKwsX7OhL8L/cwQriuKnWGHMndS0p CXgMwyhAoiWA== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="202973553" X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="202973553" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 05:20:53 -0700 IronPort-SDR: CYUJd/pgLhFnOsvxa/uwC+8CO7T94dpUjtAblJnZ/D9GKckzBJM3MGstQLAt49+H/M6lSbGotu fSzeYtyk6wcw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="619283449" Received: from intel-lenovo-legion-y540-15irh-pg0.iind.intel.com ([10.224.186.95]) by orsmga005.jf.intel.com with ESMTP; 08 Jun 2021 05:20:52 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: Kiran K Subject: [PATCH v9 04/10] Bluetooth: btintel: set get_data_path callback Date: Tue, 8 Jun 2021 17:54:49 +0530 Message-Id: <20210608122455.19583-4-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210608122455.19583-1-kiran.k@intel.com> References: <20210608122455.19583-1-kiran.k@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Read supported offload usecases and set get_data_path callback if controller suppports offload codecs. Signed-off-by: Kiran K Reviewed-by: Chethan T N Reviewed-by: Srivatsa Ravishankar --- drivers/bluetooth/btintel.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/bluetooth/btintel.h | 18 ++++++++++++++++++ drivers/bluetooth/btusb.c | 8 ++++++++ 3 files changed, 62 insertions(+) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index e44b6993cf91..95c6a1bef35e 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -1272,6 +1272,42 @@ int btintel_set_debug_features(struct hci_dev *hdev, } EXPORT_SYMBOL_GPL(btintel_set_debug_features); +int btintel_get_data_path(struct hci_dev *hdev) +{ + return 1; +} +EXPORT_SYMBOL_GPL(btintel_get_data_path); + +int btintel_read_offload_usecases(struct hci_dev *hdev, + struct intel_offload_usecases *usecases) +{ + struct sk_buff *skb; + int err = 0; + + skb = __hci_cmd_sync(hdev, 0xfc86, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Reading offload usecases failed (%ld)", + PTR_ERR(skb)); + return PTR_ERR(skb); + } + + if (skb->len < sizeof(*usecases)) { + err = -EIO; + goto error; + } + + if (skb->data[0]) { + err = -bt_to_errno(skb->data[0]); + goto error; + } + + memcpy(usecases, skb->data, sizeof(*usecases)); +error: + kfree_skb(skb); + return err; +} +EXPORT_SYMBOL_GPL(btintel_read_offload_usecases); + MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index d184064a5e7c..9bcc489680db 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -132,6 +132,11 @@ struct intel_debug_features { __u8 page1[16]; } __packed; +struct intel_offload_usecases { + __u8 status; + __u8 preset[8]; +} __packed; + #define INTEL_HW_PLATFORM(cnvx_bt) ((u8)(((cnvx_bt) & 0x0000ff00) >> 8)) #define INTEL_HW_VARIANT(cnvx_bt) ((u8)(((cnvx_bt) & 0x003f0000) >> 16)) #define INTEL_CNVX_TOP_TYPE(cnvx_top) ((cnvx_top) & 0x00000fff) @@ -175,6 +180,9 @@ int btintel_read_debug_features(struct hci_dev *hdev, struct intel_debug_features *features); int btintel_set_debug_features(struct hci_dev *hdev, const struct intel_debug_features *features); +int btintel_read_offload_usecases(struct hci_dev *hdev, + struct intel_offload_usecases *usecases); +int btintel_get_data_path(struct hci_dev *hdev); #else static inline int btintel_check_bdaddr(struct hci_dev *hdev) @@ -307,4 +315,14 @@ static inline int btintel_set_debug_features(struct hci_dev *hdev, return -EOPNOTSUPP; } +static int btintel_read_offload_usecases(struct hci_dev *hdev, + struct intel_offload_usecases *usecases) +{ + return -EOPNOTSUPP; +} + +static int btintel_get_data_path(struct hci_dev *hdev) +{ + return -EOPNOTSUPP; +} #endif diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index a9855a2dd561..1e51beec5776 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2952,6 +2952,7 @@ static int btusb_setup_intel_newgen(struct hci_dev *hdev) int err; struct intel_debug_features features; struct intel_version_tlv version; + struct intel_offload_usecases usecases; bt_dev_dbg(hdev, ""); @@ -3008,6 +3009,13 @@ static int btusb_setup_intel_newgen(struct hci_dev *hdev) /* Set DDC mask for available debug features */ btintel_set_debug_features(hdev, &features); + err = btintel_read_offload_usecases(hdev, &usecases); + if (!err) { + /* set get_data_path callback if offload is supported */ + if (usecases.preset[0] & 0x03) + hdev->get_data_path = btintel_get_data_path; + } + /* Read the Intel version information after loading the FW */ err = btintel_read_version_tlv(hdev, &version); if (err) From patchwork Tue Jun 8 12:24:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 12306699 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.0 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 01578C48BD1 for ; Tue, 8 Jun 2021 12:20:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E3B2661359 for ; Tue, 8 Jun 2021 12:20:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232532AbhFHMWs (ORCPT ); Tue, 8 Jun 2021 08:22:48 -0400 Received: from mga04.intel.com ([192.55.52.120]:22776 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232539AbhFHMWr (ORCPT ); Tue, 8 Jun 2021 08:22:47 -0400 IronPort-SDR: cJO/QdzVSZGjbrZU+o0KDOVCgeBP/gK0Dhh2IEpVCCb8D+ToNg6pJat7eHd1ZUkPb3kv6PHViS s9pJiQwQfXVQ== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="202973555" X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="202973555" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 05:20:55 -0700 IronPort-SDR: YzyNSM7ONQb18zOamwcM2en8we3om1usYIUeAUDsp4sB5hWuzzHkKd2GeHcnKRFLlszLpYvJ6q oyzOtzakTdOg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="619283454" Received: from intel-lenovo-legion-y540-15irh-pg0.iind.intel.com ([10.224.186.95]) by orsmga005.jf.intel.com with ESMTP; 08 Jun 2021 05:20:53 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: Kiran K Subject: [PATCH v9 05/10] Bluetooth: Add BT_CODEC option for getsockopt for SCO socket Date: Tue, 8 Jun 2021 17:54:50 +0530 Message-Id: <20210608122455.19583-5-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210608122455.19583-1-kiran.k@intel.com> References: <20210608122455.19583-1-kiran.k@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Add BT_CODEC option for getsockopt systemcall over SCO socket to expose the codecs supported by controller Signed-off-by: Kiran K Reviewed-by: Chethan T N Reviewed-by: Srivatsa Ravishankar --- * changes on v9: - fix typos,review comments, remove quirk include/net/bluetooth/bluetooth.h | 20 ++++++ include/net/bluetooth/hci.h | 4 ++ net/bluetooth/sco.c | 111 +++++++++++++++++++++++++++++- 3 files changed, 134 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 9125effbf448..1840756958ce 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -153,6 +153,26 @@ struct bt_voice { #define BT_SCM_PKT_STATUS 0x03 +#define BT_CODEC 19 + +struct bt_codec_caps { + __u8 len; + __u8 data[]; +} __packed; + +struct bt_codec { + __u8 id; + __le16 cid; + __le16 vid; + __u8 data_path; + __u8 num_caps; +} __packed; + +struct bt_codecs { + __u8 num_codecs; + struct bt_codec codecs[]; +} __packed; + __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 45bd9af4ce61..31a5ac8918fc 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -2619,6 +2619,10 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb) #define hci_iso_data_len(h) ((h) & 0x3fff) #define hci_iso_data_flags(h) ((h) >> 14) +/* codec transport types */ +#define TRANSPORT_ACL 0x00 +#define TRANSPORT_SCO_ESCO 0x01 + /* le24 support */ static inline void hci_cpu_to_le24(__u32 val, __u8 dst[3]) { diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index d9a4e88dacbb..98d5e24e5680 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -944,10 +944,15 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { struct sock *sk = sock->sk; - int len, err = 0; + int len, err = 0, buf_len; struct bt_voice voice; u32 phys; int pkt_status; + struct codec_list *c; + u8 num_codecs, i, __user *ptr; + struct hci_dev *hdev; + struct hci_codec_caps *caps; + __u8 data_path; BT_DBG("sk %p", sk); @@ -1012,6 +1017,110 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, err = -EFAULT; break; + case BT_CODEC: + num_codecs = 0; + buf_len = 0; + + hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR); + if (!hdev) { + err = -EBADFD; + break; + } + + if (!hdev->get_data_path) { + err = -EOPNOTSUPP; + break; + } + + hci_dev_lock(hdev); + /* find total buffer size required to copy codec + caps */ + list_for_each_entry(c, &hdev->local_codecs, list) { + if (c->transport != TRANSPORT_SCO_ESCO) + continue; + num_codecs++; + for (i = 0, caps = c->caps; i < c->num_caps; i++) { + buf_len += 1 + caps->len; + caps = (void *)&caps->data[caps->len]; + } + buf_len += sizeof(struct bt_codec); + } + hci_dev_unlock(hdev); + + buf_len += sizeof(struct bt_codecs); + if (buf_len > len) { + err = -ENOBUFS; + break; + } + ptr = optval; + + if (put_user(num_codecs, ptr)) { + err = -EFAULT; + break; + } + ptr += sizeof(num_codecs); + + hci_dev_lock(hdev); + list_for_each_entry(c, &hdev->local_codecs, list) { + if (c->transport != TRANSPORT_SCO_ESCO) + continue; + + if (put_user(c->id, ptr)) { + err = -EFAULT; + goto unlock; + } + ptr += sizeof(c->id); + + if (put_user(c->cid, ptr)) { + err = -EFAULT; + goto unlock; + } + ptr += sizeof(c->cid); + + if (put_user(c->vid, ptr)) { + err = -EFAULT; + goto unlock; + } + ptr += sizeof(c->vid); + + err = hdev->get_data_path(hdev); + if (err < 0) { + err = -EFAULT; + goto unlock; + } + + data_path = (__u8)err; + if (put_user(data_path, ptr)) { + err = -EFAULT; + goto unlock; + } + ptr += sizeof(data_path); + + if (put_user(c->num_caps, ptr)) { + err = -EFAULT; + goto unlock; + } + ptr += sizeof(c->num_caps); + + len = 0; + for (i = 0, caps = c->caps; i < c->num_caps; i++) { + len += 1 + caps->len; + caps = (void *)&caps->data[caps->len]; + } + + if (len && copy_to_user(ptr, c->caps, len)) { + err = -EFAULT; + goto unlock; + } + ptr += len; + } + + if (put_user(buf_len, optlen)) + err = -EFAULT; +unlock: + hci_dev_unlock(hdev); + + break; + default: err = -ENOPROTOOPT; break; From patchwork Tue Jun 8 12:24:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 12306703 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9043DC4743E for ; Tue, 8 Jun 2021 12:20:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 79AAF61351 for ; Tue, 8 Jun 2021 12:20:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232452AbhFHMWv (ORCPT ); Tue, 8 Jun 2021 08:22:51 -0400 Received: from mga11.intel.com ([192.55.52.93]:54897 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232547AbhFHMWv (ORCPT ); Tue, 8 Jun 2021 08:22:51 -0400 IronPort-SDR: uNg8fPT3Rh5pVRlYCuxxffRjbUvF82Si8cVCa2/3uv/sYWea2JCurA9HgFlFJ9h3dsE7SS8q8F u8mIuIi5QN4A== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="201811665" X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="201811665" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 05:20:56 -0700 IronPort-SDR: ygwOf6pUcckhc2HayX7tLuGNlXDp5I/WyH2gEF7vcuriCCG3KJukfkhyBV7Dt1EwB8n+TJPFsg 9TwT699jssTQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="619283473" Received: from intel-lenovo-legion-y540-15irh-pg0.iind.intel.com ([10.224.186.95]) by orsmga005.jf.intel.com with ESMTP; 08 Jun 2021 05:20:55 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: Kiran K Subject: [PATCH v9 06/10] Bluetooth: Add a callback function to set data path Date: Tue, 8 Jun 2021 17:54:51 +0530 Message-Id: <20210608122455.19583-6-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210608122455.19583-1-kiran.k@intel.com> References: <20210608122455.19583-1-kiran.k@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org In HFP offload usecase, Intel controllers require offload use case id (NBS or WBS) to be set before opening SCO connection. Define a new callback which gets called on setsockopt SCO socket. User space audio module is expected to set codec via setsockopt(sk, BT_CODEC, ....) before opening SCO connection. Signed-off-by: Kiran K Reviewed-by: Chethan T N Reviewed-by: Srivatsa Ravishankar --- include/net/bluetooth/hci_core.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 641477396da3..ad0024891447 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -618,6 +618,8 @@ struct hci_dev { void (*cmd_timeout)(struct hci_dev *hdev); bool (*prevent_wake)(struct hci_dev *hdev); int (*get_data_path)(struct hci_dev *hdev); + int (*set_data_path)(struct hci_dev *hdev, __u8 type, + struct bt_codec *codec); }; #define HCI_PHY_HANDLE(handle) (handle & 0xff) From patchwork Tue Jun 8 12:24:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 12306701 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 29797C47082 for ; Tue, 8 Jun 2021 12:20:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 14DD161351 for ; Tue, 8 Jun 2021 12:20:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232546AbhFHMWv (ORCPT ); Tue, 8 Jun 2021 08:22:51 -0400 Received: from mga04.intel.com ([192.55.52.120]:22782 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232539AbhFHMWu (ORCPT ); Tue, 8 Jun 2021 08:22:50 -0400 IronPort-SDR: EToPOjGBRrRqBRzoVkG/TIS+MIuC+5nUitSeIIXNH/LKbDc/9v6B2ze9+Rx2cFSVcB763ZhCnP 0B4I2GxEXzJA== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="202973562" X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="202973562" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 05:20:58 -0700 IronPort-SDR: Xvzt/NP+85A3zAeIo+IxFBIrQyePvZpTk28xbc79NjzoNLNEE0FS2TYy2jg9ZdZvU6XrplmjyS 9qjtsP/DR6Fg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="619283484" Received: from intel-lenovo-legion-y540-15irh-pg0.iind.intel.com ([10.224.186.95]) by orsmga005.jf.intel.com with ESMTP; 08 Jun 2021 05:20:56 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: Kiran K Subject: [PATCH v9 07/10] Bluetooth: btintel: define callback to set data path Date: Tue, 8 Jun 2021 17:54:52 +0530 Message-Id: <20210608122455.19583-7-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210608122455.19583-1-kiran.k@intel.com> References: <20210608122455.19583-1-kiran.k@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Adds callback function which is called to set the data path for HFP offload case before opening SCO connection Signed-off-by: Kiran K Reviewed-by: Chethan T N Reviewed-by: Srivatsa Ravishankar --- drivers/bluetooth/btintel.c | 50 +++++++++++++++++++++++++++++++++++++ drivers/bluetooth/btintel.h | 8 ++++++ drivers/bluetooth/btusb.c | 4 ++- include/net/bluetooth/hci.h | 8 ++++++ 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 95c6a1bef35e..3eba5c587ef6 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -1308,6 +1308,56 @@ int btintel_read_offload_usecases(struct hci_dev *hdev, } EXPORT_SYMBOL_GPL(btintel_read_offload_usecases); +int btintel_set_data_path(struct hci_dev *hdev, __u8 type, + struct bt_codec *codec) +{ + __u8 preset; + struct hci_op_configure_data_path *cmd; + __u8 buffer[255]; + struct sk_buff *skb; + + if (type != SCO_LINK && type != ESCO_LINK) + return -EINVAL; + + switch (codec->id) { + case 0x02: + preset = 0x00; + break; + case 0x05: + preset = 0x01; + break; + default: + return -EINVAL; + } + + cmd = (void *)buffer; + cmd->data_path_id = 0x01; + cmd->len = 1; + cmd->data[0] = preset; + + cmd->direction = 0x00; + skb = __hci_cmd_sync(hdev, HCI_CONFIGURE_DATA_PATH, sizeof(*cmd) + 1, + cmd, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "configure input data path failed (%ld)", + PTR_ERR(skb)); + return PTR_ERR(skb); + } + kfree_skb(skb); + + cmd->direction = 0x01; + skb = __hci_cmd_sync(hdev, HCI_CONFIGURE_DATA_PATH, sizeof(*cmd) + 1, + cmd, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "configure output data path failed (%ld)", + PTR_ERR(skb)); + return PTR_ERR(skb); + } + kfree_skb(skb); + return 0; +} +EXPORT_SYMBOL_GPL(btintel_set_data_path); + MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 9bcc489680db..9806970c9871 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -183,6 +183,8 @@ int btintel_set_debug_features(struct hci_dev *hdev, int btintel_read_offload_usecases(struct hci_dev *hdev, struct intel_offload_usecases *usecases); int btintel_get_data_path(struct hci_dev *hdev); +int btintel_set_data_path(struct hci_dev *hdev, __u8 type, + struct bt_codec *codec); #else static inline int btintel_check_bdaddr(struct hci_dev *hdev) @@ -325,4 +327,10 @@ static int btintel_get_data_path(struct hci_dev *hdev) { return -EOPNOTSUPP; } + +static int btintel_set_data_path(struct hci_dev *hdev, __u8 type, + struct bt_codec *codec) +{ + return -EOPNOTSUPP; +} #endif diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 1e51beec5776..afafa44752a1 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3012,8 +3012,10 @@ static int btusb_setup_intel_newgen(struct hci_dev *hdev) err = btintel_read_offload_usecases(hdev, &usecases); if (!err) { /* set get_data_path callback if offload is supported */ - if (usecases.preset[0] & 0x03) + if (usecases.preset[0] & 0x03) { hdev->get_data_path = btintel_get_data_path; + hdev->set_data_path = btintel_set_data_path; + } } /* Read the Intel version information after loading the FW */ diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 31a5ac8918fc..42963188dcea 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1250,6 +1250,14 @@ struct hci_rp_read_local_oob_ext_data { __u8 rand256[16]; } __packed; +#define HCI_CONFIGURE_DATA_PATH 0x0c83 +struct hci_op_configure_data_path { + __u8 direction; + __u8 data_path_id; + __u8 len; + __u8 data[]; +} __packed; + #define HCI_OP_READ_LOCAL_VERSION 0x1001 struct hci_rp_read_local_version { __u8 status; From patchwork Tue Jun 8 12:24:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 12306705 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0C093C4743D for ; Tue, 8 Jun 2021 12:21:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EBA2B61359 for ; Tue, 8 Jun 2021 12:20:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232550AbhFHMWw (ORCPT ); Tue, 8 Jun 2021 08:22:52 -0400 Received: from mga04.intel.com ([192.55.52.120]:22782 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232547AbhFHMWv (ORCPT ); Tue, 8 Jun 2021 08:22:51 -0400 IronPort-SDR: lcLPgaXc5f5JCV47MpHEJA6wBsgSU4SrNpymDPxi9++NOCfd5GRJQtABFqXw7C4cgBtytlCrc0 V/jnTBgbLWeg== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="202973568" X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="202973568" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 05:20:59 -0700 IronPort-SDR: DDzhWNXGu05hNdXzoDxdMOg1GXD2vEZ/CZuE6FgMSjm98Rd+oUluE2HgJPUowF+5+TUGEyuXEC J+JyBJ01rEsg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="619283490" Received: from intel-lenovo-legion-y540-15irh-pg0.iind.intel.com ([10.224.186.95]) by orsmga005.jf.intel.com with ESMTP; 08 Jun 2021 05:20:58 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: Kiran K Subject: [PATCH v9 08/10] Bluetooth: Add BT_CODEC option for setsockopt over SCO Date: Tue, 8 Jun 2021 17:54:53 +0530 Message-Id: <20210608122455.19583-8-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210608122455.19583-1-kiran.k@intel.com> References: <20210608122455.19583-1-kiran.k@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Add BT_CODEC option on setsockopt system call to allow user space audio modules to set codec. Driver also sets data path if non-HCI is selected. Signed-off-by: Kiran K Reviewed-by: Chethan T N Reviewed-by: Srivatsa Ravishankar --- include/net/bluetooth/bluetooth.h | 2 ++ net/bluetooth/sco.c | 59 +++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 1840756958ce..0e8802d09068 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -173,6 +173,8 @@ struct bt_codecs { struct bt_codec codecs[]; } __packed; +#define CODING_FORMAT_CVSD 0x02 + __printf(1, 2) void bt_info(const char *fmt, ...); __printf(1, 2) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 98d5e24e5680..5aa6808c1a22 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -67,6 +67,7 @@ struct sco_pinfo { __u32 flags; __u16 setting; __u8 cmsg_mask; + struct bt_codec codec; struct sco_conn *conn; }; @@ -438,6 +439,7 @@ static void __sco_sock_close(struct sock *sk) sock_set_flag(sk, SOCK_ZAPPED); break; } + } /* Must be called on unlocked socket. */ @@ -499,6 +501,10 @@ static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, sk->sk_state = BT_OPEN; sco_pi(sk)->setting = BT_VOICE_CVSD_16BIT; + sco_pi(sk)->codec.id = CODING_FORMAT_CVSD; + sco_pi(sk)->codec.cid = 0xffff; + sco_pi(sk)->codec.vid = 0xffff; + sco_pi(sk)->codec.data_path = 0x00; timer_setup(&sk->sk_timer, sco_sock_timeout, 0); @@ -808,6 +814,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, struct sock *sk = sock->sk; int len, err = 0; struct bt_voice voice; + struct bt_codecs *codecs; + struct hci_dev *hdev; + __u8 buffer[255]; u32 opt; BT_DBG("sk %p", sk); @@ -870,6 +879,56 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, sco_pi(sk)->cmsg_mask &= SCO_CMSG_PKT_STATUS; break; + case BT_CODEC: + if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND && + sk->sk_state != BT_CONNECT2) { + err = -EINVAL; + break; + } + + hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR); + if (!hdev) { + err = -EBADFD; + break; + } + + if (!hdev->set_data_path) { + err = -EOPNOTSUPP; + break; + } + + if (optlen < sizeof(struct bt_codecs) || optlen > 255) { + err = -EINVAL; + break; + } + + if (copy_from_sockptr(buffer, optval, optlen)) { + err = -EFAULT; + break; + } + + codecs = (void *)buffer; + + if (codecs->num_codecs > 1) { + err = -EINVAL; + break; + } + + if (codecs->codecs[0].data_path) { + err = hdev->set_data_path(hdev, SCO_LINK, + codecs->codecs); + if (err < 0) + break; + + if (codecs->codecs[0].id == 0xff) { + sco_pi(sk)->codec.cid = codecs->codecs[0].cid; + sco_pi(sk)->codec.vid = codecs->codecs[0].vid; + } + } + sco_pi(sk)->codec.id = codecs->codecs[0].id; + sco_pi(sk)->codec.data_path = codecs->codecs[0].data_path; + break; + default: err = -ENOPROTOOPT; break; From patchwork Tue Jun 8 12:24:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 12306707 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13B6AC47082 for ; Tue, 8 Jun 2021 12:21:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F379D6124C for ; Tue, 8 Jun 2021 12:21:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232556AbhFHMWx (ORCPT ); Tue, 8 Jun 2021 08:22:53 -0400 Received: from mga04.intel.com ([192.55.52.120]:22782 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232547AbhFHMWx (ORCPT ); Tue, 8 Jun 2021 08:22:53 -0400 IronPort-SDR: attbwGPa1P/OFflgkYezUjoUxlYSzTXxL+3IveKv4j2TDxJj2a6vkzMZeGIV4EqQhh936mnEjr a/3+yOuELzsQ== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="202973577" X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="202973577" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 05:21:00 -0700 IronPort-SDR: 20/O865lSZcHXPbzKNsT/D6DKTgWChiUq0BG/EpgHyekoM2CC74LdkEa05Y7YGti21vulpODoE tRw9312Vfe9A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="619283508" Received: from intel-lenovo-legion-y540-15irh-pg0.iind.intel.com ([10.224.186.95]) by orsmga005.jf.intel.com with ESMTP; 08 Jun 2021 05:20:59 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: Kiran K Subject: [PATCH v9 09/10] Bluetooth: Add support for HCI_Enhanced_Setup_Synchronous_Connection command Date: Tue, 8 Jun 2021 17:54:54 +0530 Message-Id: <20210608122455.19583-9-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210608122455.19583-1-kiran.k@intel.com> References: <20210608122455.19583-1-kiran.k@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org < HCI Command: Enhanced Setup Synchronous Connection (0x01|0x003d) plen 59 Handle: 256 Transmit bandwidth: 8000 Receive bandwidth: 8000 Max latency: 13 Packet type: 0x0380 3-EV3 may not be used 2-EV5 may not be used 3-EV5 may not be used Retransmission effort: Optimize for link quality (0x02) > HCI Event: Command Status (0x0f) plen 4 Enhanced Setup Synchronous Connection (0x01|0x003d) ncmd 1 Status: Success (0x00) > HCI Event: Synchronous Connect Complete (0x2c) plen 17 Status: Success (0x00) Handle: 257 Address: CC:98:8B:92:04:FD (SONY Visual Products Inc.) Link type: eSCO (0x02) Transmission interval: 0x0c Retransmission window: 0x06 RX packet length: 60 TX packet length: 60 Air mode: Transparent (0x03) Signed-off-by: Kiran K Reviewed-by: Chethan T N Reviewed-by: Srivatsa Ravishankar --- * changes in v9: - Fix review comments, use bt_dev_dbg instead of BT_DBG include/net/bluetooth/bluetooth.h | 3 +- include/net/bluetooth/hci.h | 34 ++++++++++ include/net/bluetooth/hci_core.h | 7 +- net/bluetooth/hci_conn.c | 107 ++++++++++++++++++++++++++++-- net/bluetooth/hci_event.c | 48 +++++++++++++- net/bluetooth/sco.c | 11 ++- 6 files changed, 201 insertions(+), 9 deletions(-) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 0e8802d09068..af2809121571 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -173,7 +173,8 @@ struct bt_codecs { struct bt_codec codecs[]; } __packed; -#define CODING_FORMAT_CVSD 0x02 +#define CODING_FORMAT_CVSD 0x02 +#define CODING_FORMAT_TRANSPARENT 0x03 __printf(1, 2) void bt_info(const char *fmt, ...); diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 42963188dcea..03241c15b5fb 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -871,6 +871,40 @@ struct hci_cp_logical_link_cancel { __u8 flow_spec_id; } __packed; +#define HCI_OP_ENHANCED_SETUP_SYNC_CONN 0x043D +struct hci_coding_format { + __u8 id; + __le16 cid; + __le16 vid; +} __packed; + +struct hci_cp_enhanced_setup_sync_conn { + __le16 handle; + __le32 tx_bandwidth; + __le32 rx_bandwidth; + struct hci_coding_format tx_coding_format; + struct hci_coding_format rx_coding_format; + __le16 tx_codec_frame_size; + __le16 rx_codec_frame_size; + __le32 in_bandwidth; + __le32 out_bandwidth; + struct hci_coding_format in_coding_format; + struct hci_coding_format out_coding_format; + __le16 in_coded_data_size; + __le16 out_coded_data_size; + __u8 in_pcm_data_format; + __u8 out_pcm_data_format; + __u8 in_pcm_sample_payload_msb_pos; + __u8 out_pcm_sample_payload_msb_pos; + __u8 in_data_path; + __u8 out_data_path; + __u8 in_trasnport_unit_size; + __u8 out_trasnport_unit_size; + __le16 max_latency; + __le16 pkt_type; + __u8 retrans_effort; +} __packed; + struct hci_rp_logical_link_cancel { __u8 status; __u8 phy_handle; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ad0024891447..4c2514135a5d 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -712,6 +712,7 @@ struct hci_conn { struct amp_mgr *amp_mgr; struct hci_conn *link; + struct bt_codec codec; void (*connect_cfm_cb) (struct hci_conn *conn, u8 status); void (*security_cfm_cb) (struct hci_conn *conn, u8 status); @@ -1094,6 +1095,7 @@ static inline struct hci_conn *hci_lookup_le_connect(struct hci_dev *hdev) int hci_disconnect(struct hci_conn *conn, __u8 reason); bool hci_setup_sync(struct hci_conn *conn, __u16 handle); +bool hci_enhanced_setup_sync(struct hci_conn *conn, __u16 handle); void hci_sco_setup(struct hci_conn *conn, __u8 status); struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, @@ -1118,7 +1120,7 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, u8 sec_level, u8 auth_type, enum conn_reasons conn_reason); struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, - __u16 setting); + __u16 setting, struct bt_codec *codec); int hci_conn_check_link_mode(struct hci_conn *conn); int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level); int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type, @@ -1439,6 +1441,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn); /* Use LL Privacy based address resolution if supported */ #define use_ll_privacy(dev) ((dev)->le_features[0] & HCI_LE_LL_PRIVACY) +/* Use enhanced synchronous connection if command is supported */ +#define use_enhanced_sco_conn(dev) ((dev)->commands[29] & 0x08) + /* Use ext scanning if set ext scan param and ext scan enable is supported */ #define use_ext_scan(dev) (((dev)->commands[37] & 0x20) && \ ((dev)->commands[37] & 0x40)) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 2b5059a56cda..9569b21adb88 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -307,6 +307,97 @@ static bool find_next_esco_param(struct hci_conn *conn, return conn->attempt <= size; } +bool hci_enhanced_setup_sync(struct hci_conn *conn, __u16 handle) +{ + struct hci_dev *hdev = conn->hdev; + struct hci_cp_enhanced_setup_sync_conn cp; + const struct sco_param *param; + + bt_dev_dbg(hdev, "hcon %p", conn); + + conn->state = BT_CONNECT; + conn->out = true; + + conn->attempt++; + + memset(&cp, 0x00, sizeof(cp)); + + cp.handle = cpu_to_le16(handle); + + cp.tx_bandwidth = cpu_to_le32(0x00001f40); + cp.rx_bandwidth = cpu_to_le32(0x00001f40); + + switch (conn->codec.id) { + case CODING_FORMAT_TRANSPARENT: + if (!find_next_esco_param(conn, esco_param_msbc, + ARRAY_SIZE(esco_param_msbc))) + return false; + param = &esco_param_msbc[conn->attempt - 1]; + cp.tx_coding_format.id = 0x03; + cp.rx_coding_format.id = 0x03; + cp.tx_codec_frame_size = __cpu_to_le16(60); + cp.rx_codec_frame_size = __cpu_to_le16(60); + cp.in_bandwidth = __cpu_to_le32(0x1f40); + cp.out_bandwidth = __cpu_to_le32(0x1f40); + cp.in_coding_format.id = 0x03; + cp.out_coding_format.id = 0x03; + cp.in_coded_data_size = __cpu_to_le16(16); + cp.out_coded_data_size = __cpu_to_le16(16); + cp.in_pcm_data_format = 2; + cp.out_pcm_data_format = 2; + cp.in_pcm_sample_payload_msb_pos = 0; + cp.out_pcm_sample_payload_msb_pos = 0; + cp.in_data_path = conn->codec.data_path; + cp.out_data_path = conn->codec.data_path; + cp.in_trasnport_unit_size = 1; + cp.out_trasnport_unit_size = 1; + break; + + case CODING_FORMAT_CVSD: + if (lmp_esco_capable(conn->link)) { + if (!find_next_esco_param(conn, esco_param_cvsd, + ARRAY_SIZE(esco_param_cvsd))) + return false; + param = &esco_param_cvsd[conn->attempt - 1]; + } else { + if (conn->attempt > ARRAY_SIZE(sco_param_cvsd)) + return false; + param = &sco_param_cvsd[conn->attempt - 1]; + } + cp.tx_coding_format.id = 2; + cp.rx_coding_format.id = 2; + cp.tx_codec_frame_size = __cpu_to_le16(60); + cp.rx_codec_frame_size = __cpu_to_le16(60); + cp.in_bandwidth = __cpu_to_le32(16000); + cp.out_bandwidth = __cpu_to_le32(16000); + cp.in_coding_format.id = 4; + cp.out_coding_format.id = 4; + cp.in_coded_data_size = __cpu_to_le16(16); + cp.out_coded_data_size = __cpu_to_le16(16); + cp.in_pcm_data_format = 2; + cp.out_pcm_data_format = 2; + cp.in_pcm_sample_payload_msb_pos = 0; + cp.out_pcm_sample_payload_msb_pos = 0; + cp.in_data_path = conn->codec.data_path; + cp.out_data_path = conn->codec.data_path; + cp.in_trasnport_unit_size = 16; + cp.out_trasnport_unit_size = 16; + break; + + default: + return false; + } + + cp.retrans_effort = param->retrans_effort; + cp.pkt_type = __cpu_to_le16(param->pkt_type); + cp.max_latency = __cpu_to_le16(param->max_latency); + + if (hci_send_cmd(hdev, HCI_OP_ENHANCED_SETUP_SYNC_CONN, sizeof(cp), &cp) < 0) + return false; + + return true; +} + bool hci_setup_sync(struct hci_conn *conn, __u16 handle) { struct hci_dev *hdev = conn->hdev; @@ -424,10 +515,14 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status) BT_DBG("hcon %p", conn); if (!status) { - if (lmp_esco_capable(conn->hdev)) - hci_setup_sync(sco, conn->handle); - else + if (lmp_esco_capable(conn->hdev)) { + if (use_enhanced_sco_conn(conn->hdev)) + hci_enhanced_setup_sync(sco, conn->handle); + else + hci_setup_sync(sco, conn->handle); + } else { hci_add_sco(sco, conn->handle); + } } else { hci_connect_cfm(sco, status); hci_conn_del(sco); @@ -1319,7 +1414,7 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, } struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, - __u16 setting) + __u16 setting, struct bt_codec *codec) { struct hci_conn *acl; struct hci_conn *sco; @@ -1344,6 +1439,10 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, hci_conn_hold(sco); sco->setting = setting; + sco->codec.id = codec->id; + sco->codec.cid = codec->cid; + sco->codec.vid = codec->vid; + sco->codec.data_path = codec->data_path; if (acl->state == BT_CONNECTED && (sco->state == BT_OPEN || sco->state == BT_CLOSED)) { diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 98ec486743ba..29a769a1a5e7 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2236,6 +2236,41 @@ static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) hci_dev_unlock(hdev); } +static void hci_cs_enhanced_setup_sync_conn(struct hci_dev *hdev, __u8 status) +{ + struct hci_cp_enhanced_setup_sync_conn *cp; + struct hci_conn *acl, *sco; + __u16 handle; + + bt_dev_dbg(hdev, "status 0x%2.2x", status); + + if (!status) + return; + + cp = hci_sent_cmd_data(hdev, HCI_OP_ENHANCED_SETUP_SYNC_CONN); + if (!cp) + return; + + handle = __le16_to_cpu(cp->handle); + + bt_dev_dbg(hdev, "handle 0x%4.4x", handle); + + hci_dev_lock(hdev); + + acl = hci_conn_hash_lookup_handle(hdev, handle); + if (acl) { + sco = acl->link; + if (sco) { + sco->state = BT_CLOSED; + + hci_connect_cfm(sco, status); + hci_conn_del(sco); + } + } + + hci_dev_unlock(hdev); +} + static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) { struct hci_cp_sniff_mode *cp; @@ -3715,6 +3750,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb, hci_cs_setup_sync_conn(hdev, ev->status); break; + case HCI_OP_ENHANCED_SETUP_SYNC_CONN: + hci_cs_enhanced_setup_sync_conn(hdev, ev->status); + break; + case HCI_OP_SNIFF_MODE: hci_cs_sniff_mode(hdev, ev->status); break; @@ -4401,8 +4440,13 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, if (conn->out) { conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | (hdev->esco_type & EDR_ESCO_MASK); - if (hci_setup_sync(conn, conn->link->handle)) - goto unlock; + if (use_enhanced_sco_conn(hdev)) { + if (hci_enhanced_setup_sync(conn, conn->link->handle)) + goto unlock; + } else { + if (hci_setup_sync(conn, conn->link->handle)) + goto unlock; + } } fallthrough; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 5aa6808c1a22..f4eea0ae3af2 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -240,7 +240,7 @@ static int sco_connect(struct sock *sk) } hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst, - sco_pi(sk)->setting); + sco_pi(sk)->setting, &sco_pi(sk)->codec); if (IS_ERR(hcon)) { err = PTR_ERR(hcon); goto done; @@ -865,6 +865,15 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, } sco_pi(sk)->setting = voice.setting; + hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, + BDADDR_BREDR); + if (!hdev) { + err = -EBADFD; + break; + } + if (use_enhanced_sco_conn(hdev) && + voice.setting == BT_VOICE_TRANSPARENT) + sco_pi(sk)->codec.id = CODING_FORMAT_TRANSPARENT; break; case BT_PKT_STATUS: From patchwork Tue Jun 8 12:24:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "K, Kiran" X-Patchwork-Id: 12306709 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE712C4743F for ; Tue, 8 Jun 2021 12:21:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 980DA6124C for ; Tue, 8 Jun 2021 12:21:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232553AbhFHMWy (ORCPT ); Tue, 8 Jun 2021 08:22:54 -0400 Received: from mga04.intel.com ([192.55.52.120]:22782 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232547AbhFHMWy (ORCPT ); Tue, 8 Jun 2021 08:22:54 -0400 IronPort-SDR: bhYvZxwPd2Gcbt0O+YaQ2htVZOVOLlNFh7KBWIGenodQo7p/Gpystp3tybWhUjtPxyoe18nNVS /CLgpOYUokqQ== X-IronPort-AV: E=McAfee;i="6200,9189,10008"; a="202973582" X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="202973582" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Jun 2021 05:21:01 -0700 IronPort-SDR: 2y4CNobpSwUuBVnMHx4LVa+wibnIwvompQLXnpeKX2wR8gajdWZZv40keO/IJysIRJFVLHRonc URue8+aFyNqw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.83,258,1616482800"; d="scan'208";a="619283524" Received: from intel-lenovo-legion-y540-15irh-pg0.iind.intel.com ([10.224.186.95]) by orsmga005.jf.intel.com with ESMTP; 08 Jun 2021 05:21:01 -0700 From: Kiran K To: linux-bluetooth@vger.kernel.org Cc: Kiran K Subject: [PATCH v9 10/10] Bluetooth: Add support for msbc coding format Date: Tue, 8 Jun 2021 17:54:55 +0530 Message-Id: <20210608122455.19583-10-kiran.k@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210608122455.19583-1-kiran.k@intel.com> References: <20210608122455.19583-1-kiran.k@intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org In Enhanced_Setup_Synchronous_Command, add support for msbc coding format Signed-off-by: Kiran K Reviewed-by: Chethan T N Reviewed-by: Srivatsa Ravishankar --- include/net/bluetooth/bluetooth.h | 1 + net/bluetooth/hci_conn.c | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index af2809121571..056699224da7 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -175,6 +175,7 @@ struct bt_codecs { #define CODING_FORMAT_CVSD 0x02 #define CODING_FORMAT_TRANSPARENT 0x03 +#define CODING_FORMAT_MSBC 0x05 __printf(1, 2) void bt_info(const char *fmt, ...); diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 9569b21adb88..73c134459361 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -328,6 +328,32 @@ bool hci_enhanced_setup_sync(struct hci_conn *conn, __u16 handle) cp.rx_bandwidth = cpu_to_le32(0x00001f40); switch (conn->codec.id) { + case CODING_FORMAT_MSBC: + if (!find_next_esco_param(conn, esco_param_msbc, + ARRAY_SIZE(esco_param_msbc))) + return false; + + param = &esco_param_msbc[conn->attempt - 1]; + cp.tx_coding_format.id = 0x05; + cp.rx_coding_format.id = 0x05; + cp.tx_codec_frame_size = __cpu_to_le16(60); + cp.rx_codec_frame_size = __cpu_to_le16(60); + cp.in_bandwidth = __cpu_to_le32(32000); + cp.out_bandwidth = __cpu_to_le32(32000); + cp.in_coding_format.id = 0x04; + cp.out_coding_format.id = 0x04; + cp.in_coded_data_size = __cpu_to_le16(16); + cp.out_coded_data_size = __cpu_to_le16(16); + cp.in_pcm_data_format = 2; + cp.out_pcm_data_format = 2; + cp.in_pcm_sample_payload_msb_pos = 0; + cp.out_pcm_sample_payload_msb_pos = 0; + cp.in_data_path = conn->codec.data_path; + cp.out_data_path = conn->codec.data_path; + cp.in_trasnport_unit_size = 1; + cp.out_trasnport_unit_size = 1; + break; + case CODING_FORMAT_TRANSPARENT: if (!find_next_esco_param(conn, esco_param_msbc, ARRAY_SIZE(esco_param_msbc))) @@ -383,7 +409,6 @@ bool hci_enhanced_setup_sync(struct hci_conn *conn, __u16 handle) cp.in_trasnport_unit_size = 16; cp.out_trasnport_unit_size = 16; break; - default: return false; }