Skip to content

Commit 248733e

Browse files
kirankrishnappa-intelVudentz
authored andcommitted
Bluetooth: Allow querying of supported offload codecs over SCO socket
Add BT_CODEC option for getsockopt systemcall to get the details of offload codecs supported over SCO socket Signed-off-by: Kiran K <[email protected]> Reviewed-by: Chethan T N <[email protected]> Reviewed-by: Srivatsa Ravishankar <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent a358ef8 commit 248733e

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

include/net/bluetooth/bluetooth.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,26 @@ struct bt_voice {
153153

154154
#define BT_SCM_PKT_STATUS 0x03
155155

156+
#define BT_CODEC 19
157+
158+
struct bt_codec_caps {
159+
__u8 len;
160+
__u8 data[];
161+
} __packed;
162+
163+
struct bt_codec {
164+
__u8 id;
165+
__u16 cid;
166+
__u16 vid;
167+
__u8 data_path;
168+
__u8 num_caps;
169+
} __packed;
170+
171+
struct bt_codecs {
172+
__u8 num_codecs;
173+
struct bt_codec codecs[];
174+
} __packed;
175+
156176
__printf(1, 2)
157177
void bt_info(const char *fmt, ...);
158178
__printf(1, 2)

include/net/bluetooth/hci.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ enum {
331331
HCI_CMD_PENDING,
332332
HCI_FORCE_NO_MITM,
333333
HCI_QUALITY_REPORT,
334+
HCI_OFFLOAD_CODECS_ENABLED,
334335

335336
__HCI_NUM_FLAGS,
336337
};
@@ -2622,6 +2623,9 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb)
26222623
#define hci_iso_data_len(h) ((h) & 0x3fff)
26232624
#define hci_iso_data_flags(h) ((h) >> 14)
26242625

2626+
/* codec transport types */
2627+
#define HCI_TRANSPORT_SCO_ESCO 0x01
2628+
26252629
/* le24 support */
26262630
static inline void hci_cpu_to_le24(__u32 val, __u8 dst[3])
26272631
{

include/net/bluetooth/hci_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,7 @@ struct hci_dev {
619619
void (*cmd_timeout)(struct hci_dev *hdev);
620620
bool (*prevent_wake)(struct hci_dev *hdev);
621621
int (*set_quality_report)(struct hci_dev *hdev, bool enable);
622+
int (*get_data_path_id)(struct hci_dev *hdev, __u8 *data_path);
622623
};
623624

624625
#define HCI_PHY_HANDLE(handle) (handle & 0xff)

net/bluetooth/sco.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,12 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
972972
struct bt_voice voice;
973973
u32 phys;
974974
int pkt_status;
975+
int buf_len;
976+
struct codec_list *c;
977+
u8 num_codecs, i, __user *ptr;
978+
struct hci_dev *hdev;
979+
struct hci_codec_caps *caps;
980+
struct bt_codec codec;
975981

976982
BT_DBG("sk %p", sk);
977983

@@ -1036,6 +1042,101 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
10361042
err = -EFAULT;
10371043
break;
10381044

1045+
case BT_CODEC:
1046+
num_codecs = 0;
1047+
buf_len = 0;
1048+
1049+
hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
1050+
if (!hdev) {
1051+
err = -EBADFD;
1052+
break;
1053+
}
1054+
1055+
if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED)) {
1056+
hci_dev_put(hdev);
1057+
err = -EOPNOTSUPP;
1058+
break;
1059+
}
1060+
1061+
if (!hdev->get_data_path_id) {
1062+
hci_dev_put(hdev);
1063+
err = -EOPNOTSUPP;
1064+
break;
1065+
}
1066+
1067+
/* find total buffer size required to copy codec + caps */
1068+
hci_dev_lock(hdev);
1069+
list_for_each_entry(c, &hdev->local_codecs, list) {
1070+
if (c->transport != HCI_TRANSPORT_SCO_ESCO)
1071+
continue;
1072+
num_codecs++;
1073+
for (i = 0, caps = c->caps; i < c->num_caps; i++) {
1074+
buf_len += 1 + caps->len;
1075+
caps = (void *)&caps->data[caps->len];
1076+
}
1077+
buf_len += sizeof(struct bt_codec);
1078+
}
1079+
hci_dev_unlock(hdev);
1080+
1081+
buf_len += sizeof(struct bt_codecs);
1082+
if (buf_len > len) {
1083+
hci_dev_put(hdev);
1084+
err = -ENOBUFS;
1085+
break;
1086+
}
1087+
ptr = optval;
1088+
1089+
if (put_user(num_codecs, ptr)) {
1090+
hci_dev_put(hdev);
1091+
err = -EFAULT;
1092+
break;
1093+
}
1094+
ptr += sizeof(num_codecs);
1095+
1096+
/* Iterate all the codecs supported over SCO and populate
1097+
* codec data
1098+
*/
1099+
hci_dev_lock(hdev);
1100+
list_for_each_entry(c, &hdev->local_codecs, list) {
1101+
if (c->transport != HCI_TRANSPORT_SCO_ESCO)
1102+
continue;
1103+
1104+
codec.id = c->id;
1105+
codec.cid = c->cid;
1106+
codec.vid = c->vid;
1107+
err = hdev->get_data_path_id(hdev, &codec.data_path);
1108+
if (err < 0)
1109+
break;
1110+
codec.num_caps = c->num_caps;
1111+
if (copy_to_user(ptr, &codec, sizeof(codec))) {
1112+
err = -EFAULT;
1113+
break;
1114+
}
1115+
ptr += sizeof(codec);
1116+
1117+
/* find codec capabilities data length */
1118+
len = 0;
1119+
for (i = 0, caps = c->caps; i < c->num_caps; i++) {
1120+
len += 1 + caps->len;
1121+
caps = (void *)&caps->data[caps->len];
1122+
}
1123+
1124+
/* copy codec capabilities data */
1125+
if (len && copy_to_user(ptr, c->caps, len)) {
1126+
err = -EFAULT;
1127+
break;
1128+
}
1129+
ptr += len;
1130+
}
1131+
1132+
if (!err && put_user(buf_len, optlen))
1133+
err = -EFAULT;
1134+
1135+
hci_dev_unlock(hdev);
1136+
hci_dev_put(hdev);
1137+
1138+
break;
1139+
10391140
default:
10401141
err = -ENOPROTOOPT;
10411142
break;

0 commit comments

Comments
 (0)