diff mbox series

[v1,1/7] Bluetooth: Refactor code to read supported codecs in getsockopt

Message ID 20211008135853.8604-1-kiran.k@intel.com (mailing list archive)
State Superseded
Headers show
Series [v1,1/7] Bluetooth: Refactor code to read supported codecs in getsockopt | expand

Checks

Context Check Description
tedd_an/checkpatch fail [v1,1/7] Bluetooth: Refactor code to read supported codecs in getsockopt\ERROR:GERRIT_CHANGE_ID: Remove Gerrit Change-Id's before submitting upstream #56: Change-Id: I080ed7ca8abd824d3af10859afd808bad28ee86d total: 1 errors, 0 warnings, 0 checks, 218 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/12545457.patch has style problems, please review. NOTE: Ignored message types: UNKNOWN_COMMIT_ID NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS.
tedd_an/gitlint success Gitlint PASS
tedd_an/buildkernel success Build Kernel PASS
tedd_an/testrunnersetup success Test Runner Setup PASS
tedd_an/testrunnerl2cap-tester success Total: 40, Passed: 40 (100.0%), Failed: 0, Not Run: 0
tedd_an/testrunnerbnep-tester success Total: 1, Passed: 1 (100.0%), Failed: 0, Not Run: 0
tedd_an/testrunnermgmt-tester success Total: 463, Passed: 463 (100.0%), Failed: 0, Not Run: 0
tedd_an/testrunnerrfcomm-tester success Total: 9, Passed: 9 (100.0%), Failed: 0, Not Run: 0
tedd_an/testrunnersco-tester success Total: 12, Passed: 12 (100.0%), Failed: 0, Not Run: 0
tedd_an/testrunnersmp-tester success Total: 8, Passed: 8 (100.0%), Failed: 0, Not Run: 0
tedd_an/testrunneruserchan-tester success Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0

Commit Message

K, Kiran Oct. 8, 2021, 1:58 p.m. UTC
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 <kiran.k@intel.com>
Change-Id: I080ed7ca8abd824d3af10859afd808bad28ee86d
---
 net/bluetooth/hci_codec.c | 88 +++++++++++++++++++++++++++++++++++
 net/bluetooth/hci_codec.h |  2 +
 net/bluetooth/sco.c       | 98 +++------------------------------------
 3 files changed, 96 insertions(+), 92 deletions(-)

Comments

K, Kiran Oct. 8, 2021, 2 p.m. UTC | #1
Please ignore this v1 patchset.  Need to remove ChangeId  in commit message in patches. I will send update v2 version.

Thanks,
Kiran


> -----Original Message-----
> From: K, Kiran <kiran.k@intel.com>
> Sent: Friday, October 8, 2021 7:29 PM
> To: linux-bluetooth@vger.kernel.org
> Cc: Srivatsa, Ravishankar <ravishankar.srivatsa@intel.com>; Tumkur
> Narayan, Chethan <chethan.tumkur.narayan@intel.com>; Von Dentz, Luiz
> <luiz.von.dentz@intel.com>; K, Kiran <kiran.k@intel.com>
> Subject: [PATCH v1 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 <kiran.k@intel.com>
> Change-Id: I080ed7ca8abd824d3af10859afd808bad28ee86d
> ---
>  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
bluez.test.bot@gmail.com Oct. 8, 2021, 3:07 p.m. UTC | #2
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=560011

---Test result---

Test Summary:
CheckPatch                    FAIL      12.98 seconds
GitLint                       PASS      6.51 seconds
BuildKernel                   PASS      659.34 seconds
TestRunner: Setup             PASS      455.35 seconds
TestRunner: l2cap-tester      PASS      9.94 seconds
TestRunner: bnep-tester       PASS      5.37 seconds
TestRunner: mgmt-tester       PASS      85.89 seconds
TestRunner: rfcomm-tester     PASS      6.77 seconds
TestRunner: sco-tester        PASS      6.96 seconds
TestRunner: smp-tester        PASS      6.66 seconds
TestRunner: userchan-tester   PASS      5.64 seconds

Details
##############################
Test: CheckPatch - FAIL - 12.98 seconds
Run checkpatch.pl script with rule in .checkpatch.conf
[v1,1/7] Bluetooth: Refactor code to read supported codecs in getsockopt\ERROR:GERRIT_CHANGE_ID: Remove Gerrit Change-Id's before submitting upstream
#56: 
Change-Id: I080ed7ca8abd824d3af10859afd808bad28ee86d

total: 1 errors, 0 warnings, 0 checks, 218 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12545457.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.

[v1,2/7] Bluetooth: Support reading of codecs supported over l2cap socket\ERROR:GERRIT_CHANGE_ID: Remove Gerrit Change-Id's before submitting upstream
#57: 
Change-Id: I1592f3bb1167771bfb2cb9114438e473ea372c90

total: 1 errors, 0 warnings, 0 checks, 39 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12545459.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.

[v1,3/7] Bluetooth: btintel: cache offload use case data\ERROR:GERRIT_CHANGE_ID: Remove Gerrit Change-Id's before submitting upstream
#57: 
Change-Id: I4057eb3ce1412baf0f0ba1bb83bbe71aaefaf9fc

total: 1 errors, 0 warnings, 29 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12545461.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.

[v1,4/7] Bluetooth: Pass transport type in get_data_path_id\ERROR:GERRIT_CHANGE_ID: Remove Gerrit Change-Id's before submitting upstream
#57: 
Change-Id: Ie3f0c50cb07b6cf8e8ae001361940e8b1411b461

total: 1 errors, 0 warnings, 0 checks, 110 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12545463.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.

[v1,5/7] Bluetooth: btintel: Add support to fetch data path id for a2dp offload\ERROR:GERRIT_CHANGE_ID: Remove Gerrit Change-Id's before submitting upstream
#57: 
Change-Id: Id05bff65e5e88ac4e6379d4184a5775fb6330c6d

total: 1 errors, 0 warnings, 45 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12545465.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.

[v1,6/7] Bluetooth: Remove unused member in struct hci_vnd_codec_v2\ERROR:GERRIT_CHANGE_ID: Remove Gerrit Change-Id's before submitting upstream
#56: 
Change-Id: I466f0ecac850115d15dfe72a943fbf3f31baf18d

ERROR:MISSING_SIGN_OFF: Missing Signed-off-by: line(s)

total: 2 errors, 0 warnings, 7 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12545467.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.

[v1,7/7] Bluetooth: Read Output codec capabilities\ERROR:GERRIT_CHANGE_ID: Remove Gerrit Change-Id's before submitting upstream
#55: 
Change-Id: I68c9aaca0fb0f57be3cceb33251b39acfae58aaa

ERROR:MISSING_SIGN_OFF: Missing Signed-off-by: line(s)

total: 2 errors, 0 warnings, 0 checks, 38 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12545469.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.




---
Regards,
Linux Bluetooth
diff mbox series

Patch

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: