2021-10-08 14:04:31

by Kiran K

[permalink] [raw]
Subject: [PATCH v2 1/7] Bluetooth: Refactor code to read supported codecs in getsockopt

This patch moves reading of supported codecs from cache to a new
function to reuse over L2CAP sockets to be used in a2dp offload
use case.

Signed-off-by: Kiran K <[email protected]>
---
net/bluetooth/hci_codec.c | 88 +++++++++++++++++++++++++++++++++++
net/bluetooth/hci_codec.h | 2 +
net/bluetooth/sco.c | 98 +++------------------------------------
3 files changed, 96 insertions(+), 92 deletions(-)

diff --git a/net/bluetooth/hci_codec.c b/net/bluetooth/hci_codec.c
index 38201532f58e..f4d8d3a253d8 100644
--- a/net/bluetooth/hci_codec.c
+++ b/net/bluetooth/hci_codec.c
@@ -250,3 +250,91 @@ void hci_read_supported_codecs_v2(struct hci_dev *hdev)
error:
kfree_skb(skb);
}
+
+int hci_get_supported_codecs(struct hci_dev *hdev, u8 type, char __user *optval,
+ int __user *optlen, int len)
+{
+ int n = 0, buf_len = 0, err = 0;
+ struct hci_codec_caps *caps;
+ struct bt_codec codec;
+ u8 num_codecs = 0, i, __user *ptr;
+ struct codec_list *c;
+
+ if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED)) {
+ err = -EOPNOTSUPP;
+ goto error;
+ }
+
+ if (!hdev->get_data_path_id) {
+ err = -EOPNOTSUPP;
+ goto error;
+ }
+
+ /* find total buffer size required to copy codec + capabilities */
+ hci_dev_lock(hdev);
+ list_for_each_entry(c, &hdev->local_codecs, list) {
+ if (c->transport != type)
+ 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;
+ goto error;
+ }
+ ptr = optval;
+
+ if (put_user(num_codecs, ptr)) {
+ err = -EFAULT;
+ goto error;
+ }
+ ptr += sizeof(num_codecs);
+
+ /* Iterate over all the codecs on required transport */
+ hci_dev_lock(hdev);
+ list_for_each_entry(c, &hdev->local_codecs, list) {
+ if (c->transport != type)
+ continue;
+
+ codec.id = c->id;
+ codec.cid = c->cid;
+ codec.vid = c->vid;
+ err = hdev->get_data_path_id(hdev, &codec.data_path);
+ if (err < 0)
+ break;
+ codec.num_caps = c->num_caps;
+ if (copy_to_user(ptr, &codec, sizeof(codec))) {
+ err = -EFAULT;
+ break;
+ }
+ ptr += sizeof(codec);
+
+ /* find codec capabilities data length */
+ n = 0;
+ for (i = 0, caps = c->caps; i < c->num_caps; i++) {
+ n += 1 + caps->len;
+ caps = (void *)&caps->data[caps->len];
+ }
+
+ /* copy codec capabilities data */
+ if (n && copy_to_user(ptr, c->caps, n)) {
+ err = -EFAULT;
+ break;
+ }
+ ptr += n;
+ }
+ hci_dev_unlock(hdev);
+
+ if (!err && put_user(buf_len, optlen))
+ err = -EFAULT;
+
+error:
+ return err;
+}
diff --git a/net/bluetooth/hci_codec.h b/net/bluetooth/hci_codec.h
index a2751930f123..6e849c7d75b9 100644
--- a/net/bluetooth/hci_codec.h
+++ b/net/bluetooth/hci_codec.h
@@ -5,3 +5,5 @@
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);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 8eabf41b2993..0af814c13b5f 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -33,6 +33,8 @@
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/sco.h>

+#include "hci_codec.h"
+
static bool disable_esco;

static const struct proto_ops sco_sock_ops;
@@ -1032,12 +1034,7 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
struct bt_voice voice;
u32 phys;
int pkt_status;
- int buf_len;
- struct codec_list *c;
- u8 num_codecs, i, __user *ptr;
struct hci_dev *hdev;
- struct hci_codec_caps *caps;
- struct bt_codec codec;

BT_DBG("sk %p", sk);

@@ -1103,98 +1100,15 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
break;

case BT_CODEC:
- num_codecs = 0;
- buf_len = 0;
-
- hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
+ hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src,
+ BDADDR_BREDR);
if (!hdev) {
err = -EBADFD;
break;
}
-
- if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED)) {
- hci_dev_put(hdev);
- err = -EOPNOTSUPP;
- break;
- }
-
- if (!hdev->get_data_path_id) {
- hci_dev_put(hdev);
- err = -EOPNOTSUPP;
- break;
- }
-
- /* find total buffer size required to copy codec + caps */
- hci_dev_lock(hdev);
- list_for_each_entry(c, &hdev->local_codecs, list) {
- if (c->transport != HCI_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) {
- hci_dev_put(hdev);
- err = -ENOBUFS;
- break;
- }
- ptr = optval;
-
- if (put_user(num_codecs, ptr)) {
- hci_dev_put(hdev);
- err = -EFAULT;
- break;
- }
- ptr += sizeof(num_codecs);
-
- /* Iterate all the codecs supported over SCO and populate
- * codec data
- */
- hci_dev_lock(hdev);
- list_for_each_entry(c, &hdev->local_codecs, list) {
- if (c->transport != HCI_TRANSPORT_SCO_ESCO)
- continue;
-
- codec.id = c->id;
- codec.cid = c->cid;
- codec.vid = c->vid;
- err = hdev->get_data_path_id(hdev, &codec.data_path);
- if (err < 0)
- break;
- codec.num_caps = c->num_caps;
- if (copy_to_user(ptr, &codec, sizeof(codec))) {
- err = -EFAULT;
- break;
- }
- ptr += sizeof(codec);
-
- /* find codec capabilities data length */
- len = 0;
- for (i = 0, caps = c->caps; i < c->num_caps; i++) {
- len += 1 + caps->len;
- caps = (void *)&caps->data[caps->len];
- }
-
- /* copy codec capabilities data */
- if (len && copy_to_user(ptr, c->caps, len)) {
- err = -EFAULT;
- break;
- }
- ptr += len;
- }
-
- if (!err && put_user(buf_len, optlen))
- err = -EFAULT;
-
- hci_dev_unlock(hdev);
+ err = hci_get_supported_codecs(hdev, HCI_TRANSPORT_SCO_ESCO,
+ optval, optlen, len);
hci_dev_put(hdev);
-
break;

default:
--
2.17.1


2021-10-08 14:04:34

by Kiran K

[permalink] [raw]
Subject: [PATCH v2 7/7] Bluetooth: Read Output codec capabilities

When reading codec capabilities, read output (controller to host)
capabilities also along with input (host to controller) capabilities.

Signed-off-by: Kiran K <[email protected]>
---
net/bluetooth/hci_codec.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/net/bluetooth/hci_codec.c b/net/bluetooth/hci_codec.c
index 6d4e5353f05c..c6bd934dcf36 100644
--- a/net/bluetooth/hci_codec.c
+++ b/net/bluetooth/hci_codec.c
@@ -159,6 +159,9 @@ void hci_read_supported_codecs(struct hci_dev *hdev)
caps.id = std_codecs->codec[i];
caps.direction = 0x00;
hci_read_codec_capabilities(hdev, LOCAL_CODEC_ACL_MASK, &caps);
+
+ caps.direction = 0x01;
+ hci_read_codec_capabilities(hdev, LOCAL_CODEC_ACL_MASK, &caps);
}

skb_pull(skb, flex_array_size(std_codecs, codec, std_codecs->num)
@@ -179,6 +182,9 @@ void hci_read_supported_codecs(struct hci_dev *hdev)
caps.vid = vnd_codecs->codec[i].vid;
caps.direction = 0x00;
hci_read_codec_capabilities(hdev, LOCAL_CODEC_ACL_MASK, &caps);
+
+ caps.direction = 0x01;
+ hci_read_codec_capabilities(hdev, LOCAL_CODEC_ACL_MASK, &caps);
}

error:
@@ -224,6 +230,10 @@ void hci_read_supported_codecs_v2(struct hci_dev *hdev)

for (i = 0; i < std_codecs->num; i++) {
caps.id = std_codecs->codec[i].id;
+ caps.direction = 0x00;
+ hci_read_codec_capabilities(hdev, std_codecs->codec[i].transport,
+ &caps);
+ caps.direction = 0x01;
hci_read_codec_capabilities(hdev, std_codecs->codec[i].transport,
&caps);
}
@@ -243,6 +253,10 @@ void hci_read_supported_codecs_v2(struct hci_dev *hdev)
caps.id = 0xFF;
caps.cid = vnd_codecs->codec[i].cid;
caps.vid = vnd_codecs->codec[i].vid;
+ caps.direction = 0x00;
+ hci_read_codec_capabilities(hdev, vnd_codecs->codec[i].transport,
+ &caps);
+ caps.direction = 0x01;
hci_read_codec_capabilities(hdev, vnd_codecs->codec[i].transport,
&caps);
}
--
2.17.1

2021-10-08 14:04:52

by Kiran K

[permalink] [raw]
Subject: [PATCH v2 3/7] Bluetooth: btintel: cache offload use case data

Keep a copy of use cases preset information in
driver data. Use cases preset data can be re-used
later instead of reading from controller every time.

Signed-off-by: Kiran K <[email protected]>
---
drivers/bluetooth/btintel.c | 6 ++++++
drivers/bluetooth/btintel.h | 1 +
2 files changed, 7 insertions(+)

diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 9359bff47296..f1431143eff5 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -2219,6 +2219,7 @@ static int btintel_configure_offload(struct hci_dev *hdev)
struct sk_buff *skb;
int err = 0;
struct intel_offload_use_cases *use_cases;
+ struct btintel_data *intel_data;

skb = __hci_cmd_sync(hdev, 0xfc86, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
@@ -2239,10 +2240,15 @@ static int btintel_configure_offload(struct hci_dev *hdev)
goto error;
}

+ intel_data = hci_get_priv((hdev));
+
+ intel_data->use_cases = *use_cases;
+
if (use_cases->preset[0] & 0x03) {
hdev->get_data_path_id = btintel_get_data_path_id;
hdev->get_codec_config_data = btintel_get_codec_config_data;
}
+
error:
kfree_skb(skb);
return err;
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
index e500c0d7a729..091528d75256 100644
--- a/drivers/bluetooth/btintel.h
+++ b/drivers/bluetooth/btintel.h
@@ -158,6 +158,7 @@ enum {

struct btintel_data {
DECLARE_BITMAP(flags, __INTEL_NUM_FLAGS);
+ struct intel_offload_use_cases use_cases;
};

#define btintel_set_flag(hdev, nr) \
--
2.17.1

2021-10-08 14:04:56

by Kiran K

[permalink] [raw]
Subject: [PATCH v2 2/7] Bluetooth: Support reading of codecs supported over l2cap socket

Codecs supported for A2DP offload use case are returned over l2cap
socket. Add BT_CODEC option to getsockopt to return the codecs.

Signed-off-by: Kiran K <[email protected]>
---
include/net/bluetooth/hci.h | 1 +
net/bluetooth/l2cap_sock.c | 14 ++++++++++++++
2 files changed, 15 insertions(+)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 63065bc01b76..451d491f7f68 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -2666,6 +2666,7 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb)
#define hci_iso_data_flags(h) ((h) >> 14)

/* codec transport types */
+#define HCI_TRANSPORT_ACL 0x00
#define HCI_TRANSPORT_SCO_ESCO 0x01

/* le24 support */
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 160c016a5dfb..06f8ea681972 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -36,6 +36,7 @@
#include <net/bluetooth/l2cap.h>

#include "smp.h"
+#include "hci_codec.h"

static struct bt_sock_list l2cap_sk_list = {
.lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
@@ -549,6 +550,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
struct bt_power pwr;
u32 phys;
int len, mode, err = 0;
+ struct hci_dev *hdev;

BT_DBG("sk %p", sk);

@@ -685,6 +687,18 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
err = -EFAULT;
break;

+ case BT_CODEC:
+ hdev = hci_get_route(BDADDR_ANY, &chan->src, BDADDR_BREDR);
+ if (!hdev) {
+ err = -EBADFD;
+ break;
+ }
+
+ err = hci_get_supported_codecs(hdev, HCI_TRANSPORT_ACL, optval,
+ optlen, len);
+ hci_dev_put(hdev);
+ break;
+
default:
err = -ENOPROTOOPT;
break;
--
2.17.1

2021-10-08 14:04:58

by Kiran K

[permalink] [raw]
Subject: [PATCH v2 4/7] Bluetooth: Pass transport type in get_data_path_id

To support fetching of data path id for other transport types
like a2dp, le audio, pass an additional parameter to get_data_path_id
callback function.

Signed-off-by: Kiran K <[email protected]>
---
drivers/bluetooth/btintel.c | 19 +++++++++++++++----
drivers/bluetooth/hci_vhci.c | 6 +++++-
include/net/bluetooth/hci_core.h | 3 ++-
net/bluetooth/hci_codec.c | 9 ++++++---
net/bluetooth/hci_conn.c | 3 ++-
net/bluetooth/hci_request.c | 5 +++--
net/bluetooth/hci_request.h | 3 ++-
7 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index f1431143eff5..de4667179efb 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -2207,11 +2207,22 @@ static int btintel_get_codec_config_data(struct hci_dev *hdev,
return err;
}

-static int btintel_get_data_path_id(struct hci_dev *hdev, __u8 *data_path_id)
+static int btintel_get_data_path_id(struct hci_dev *hdev, __u8 transport,
+ __u8 *data_path_id)
{
- /* Intel uses 1 as data path id for all the usecases */
- *data_path_id = 1;
- return 0;
+ struct btintel_data *intel_data;
+
+ if (transport != HCI_TRANSPORT_SCO_ESCO)
+ return -EINVAL;
+
+ intel_data = hci_get_priv((hdev));
+
+ if (intel_data->use_cases.preset[0] & 0x03) {
+ /* Intel uses 1 as data path id for all the usecases */
+ *data_path_id = 1;
+ return 0;
+ }
+ return -EOPNOTSUPP;
}

static int btintel_configure_offload(struct hci_dev *hdev)
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 56c6b22be10b..a011d5b5694a 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -78,8 +78,12 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0;
}

-static int vhci_get_data_path_id(struct hci_dev *hdev, u8 *data_path_id)
+static int vhci_get_data_path_id(struct hci_dev *hdev, u8 transport,
+ u8 *data_path_id)
{
+ if (transport != HCI_TRANSPORT_SCO_ESCO)
+ return -EINVAL;
+
*data_path_id = 0;
return 0;
}
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index dd8840e70e25..8b8b45f6d5bd 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -619,7 +619,8 @@ struct hci_dev {
void (*cmd_timeout)(struct hci_dev *hdev);
bool (*wakeup)(struct hci_dev *hdev);
int (*set_quality_report)(struct hci_dev *hdev, bool enable);
- int (*get_data_path_id)(struct hci_dev *hdev, __u8 *data_path);
+ int (*get_data_path_id)(struct hci_dev *hdev, __u8 transport,
+ __u8 *data_path);
int (*get_codec_config_data)(struct hci_dev *hdev, __u8 type,
struct bt_codec *codec, __u8 *vnd_len,
__u8 **vnd_data);
diff --git a/net/bluetooth/hci_codec.c b/net/bluetooth/hci_codec.c
index f4d8d3a253d8..6d4e5353f05c 100644
--- a/net/bluetooth/hci_codec.c
+++ b/net/bluetooth/hci_codec.c
@@ -259,6 +259,7 @@ int hci_get_supported_codecs(struct hci_dev *hdev, u8 type, char __user *optval,
struct bt_codec codec;
u8 num_codecs = 0, i, __user *ptr;
struct codec_list *c;
+ u8 data_path;

if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED)) {
err = -EOPNOTSUPP;
@@ -270,6 +271,10 @@ int hci_get_supported_codecs(struct hci_dev *hdev, u8 type, char __user *optval,
goto error;
}

+ err = hdev->get_data_path_id(hdev, type, &data_path);
+ if (err < 0)
+ goto error;
+
/* find total buffer size required to copy codec + capabilities */
hci_dev_lock(hdev);
list_for_each_entry(c, &hdev->local_codecs, list) {
@@ -306,9 +311,7 @@ int hci_get_supported_codecs(struct hci_dev *hdev, u8 type, char __user *optval,
codec.id = c->id;
codec.cid = c->cid;
codec.vid = c->vid;
- err = hdev->get_data_path_id(hdev, &codec.data_path);
- if (err < 0)
- break;
+ codec.data_path = data_path;
codec.num_caps = c->num_caps;
if (copy_to_user(ptr, &codec, sizeof(codec))) {
err = -EFAULT;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index bd669c95b9a7..62192f463e5c 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -317,7 +317,8 @@ static bool hci_enhanced_setup_sync_conn(struct hci_conn *conn, __u16 handle)

/* for offload use case, codec needs to configured before opening SCO */
if (conn->codec.data_path)
- hci_req_configure_datapath(hdev, &conn->codec);
+ hci_req_configure_datapath(hdev, HCI_TRANSPORT_SCO_ESCO,
+ &conn->codec);

conn->state = BT_CONNECT;
conn->out = true;
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 92611bfc0b9e..34a104a2ca32 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -2950,7 +2950,8 @@ static void config_data_path_complete(struct hci_dev *hdev, u8 status,
bt_dev_dbg(hdev, "status %u", status);
}

-int hci_req_configure_datapath(struct hci_dev *hdev, struct bt_codec *codec)
+int hci_req_configure_datapath(struct hci_dev *hdev, u8 transport,
+ struct bt_codec *codec)
{
struct hci_request req;
int err;
@@ -2970,7 +2971,7 @@ int hci_req_configure_datapath(struct hci_dev *hdev, struct bt_codec *codec)
goto error;
}

- err = hdev->get_data_path_id(hdev, &cmd->data_path_id);
+ err = hdev->get_data_path_id(hdev, transport, &cmd->data_path_id);
if (err < 0)
goto error;

diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h
index f31420f58525..d80a4e277a20 100644
--- a/net/bluetooth/hci_request.h
+++ b/net/bluetooth/hci_request.h
@@ -101,7 +101,8 @@ void __hci_req_update_class(struct hci_request *req);
/* Returns true if HCI commands were queued */
bool hci_req_stop_discovery(struct hci_request *req);

-int hci_req_configure_datapath(struct hci_dev *hdev, struct bt_codec *codec);
+int hci_req_configure_datapath(struct hci_dev *hdev, u8 transport,
+ struct bt_codec *codec);

static inline void hci_req_update_scan(struct hci_dev *hdev)
{
--
2.17.1

2021-10-08 15:09:48

by bluez.test.bot

[permalink] [raw]
Subject: RE: [v2,1/7] Bluetooth: Refactor code to read supported codecs in getsockopt

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=560017

---Test result---

Test Summary:
CheckPatch PASS 12.63 seconds
GitLint PASS 6.50 seconds
BuildKernel PASS 655.63 seconds
TestRunner: Setup PASS 488.22 seconds
TestRunner: l2cap-tester PASS 10.36 seconds
TestRunner: bnep-tester PASS 5.72 seconds
TestRunner: mgmt-tester PASS 89.14 seconds
TestRunner: rfcomm-tester PASS 7.07 seconds
TestRunner: sco-tester PASS 7.24 seconds
TestRunner: smp-tester PASS 7.11 seconds
TestRunner: userchan-tester PASS 6.27 seconds



---
Regards,
Linux Bluetooth


Attachments:
l2cap-tester.log (43.32 kB)
bnep-tester.log (3.48 kB)
mgmt-tester.log (622.86 kB)
rfcomm-tester.log (11.41 kB)
sco-tester.log (13.60 kB)
smp-tester.log (11.55 kB)
userchan-tester.log (6.22 kB)
Download all attachments