Bluetooth: Add BTPROTO_ISO socket type
This introduces a new socket type BTPROTO_ISO which can be enabled with use of ISO Socket experiemental UUID, it can used to initiate/accept connections and transfer packets between userspace and kernel similarly to how BTPROTO_SCO works: Central -> uses connect with address set to destination bdaddr: > tools/isotest -s 00:AA:01:00:00:00 Peripheral -> uses listen: > tools/isotest -d Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
26afbd826e
commit
ccf74f2390
@ -590,6 +590,27 @@ static inline void sco_exit(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_LE)
|
||||
int iso_init(void);
|
||||
int iso_exit(void);
|
||||
bool iso_enabled(void);
|
||||
#else
|
||||
static inline int iso_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int iso_exit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool iso_enabled(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
int mgmt_init(void);
|
||||
void mgmt_exit(void);
|
||||
|
||||
|
@ -843,6 +843,21 @@ static inline void sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_LE)
|
||||
int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
|
||||
void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags);
|
||||
#else
|
||||
static inline int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
||||
__u8 *flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void iso_recv(struct hci_conn *hcon, struct sk_buff *skb,
|
||||
u16 flags)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ----- Inquiry cache ----- */
|
||||
#define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */
|
||||
#define INQUIRY_ENTRY_AGE_MAX (HZ*60) /* 60 seconds */
|
||||
@ -1640,8 +1655,7 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
||||
return sco_connect_ind(hdev, bdaddr, flags);
|
||||
|
||||
case ISO_LINK:
|
||||
/* TODO: Handle connection indication */
|
||||
return -EINVAL;
|
||||
return iso_connect_ind(hdev, bdaddr, flags);
|
||||
|
||||
default:
|
||||
BT_ERR("unknown link type %d", type);
|
||||
|
21
include/net/bluetooth/iso.h
Normal file
21
include/net/bluetooth/iso.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __ISO_H
|
||||
#define __ISO_H
|
||||
|
||||
/* ISO defaults */
|
||||
#define ISO_DEFAULT_MTU 251
|
||||
|
||||
/* ISO socket address */
|
||||
struct sockaddr_iso {
|
||||
sa_family_t iso_family;
|
||||
bdaddr_t iso_bdaddr;
|
||||
__u8 iso_bdaddr_type;
|
||||
};
|
||||
|
||||
#endif /* __ISO_H */
|
@ -18,6 +18,7 @@ bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
|
||||
eir.o hci_sync.o
|
||||
|
||||
bluetooth-$(CONFIG_BT_BREDR) += sco.o
|
||||
bluetooth-$(CONFIG_BT_LE) += iso.o
|
||||
bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o
|
||||
bluetooth-$(CONFIG_BT_LEDS) += leds.o
|
||||
bluetooth-$(CONFIG_BT_MSFTEXT) += msft.o
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include "selftest.h"
|
||||
|
||||
/* Bluetooth sockets */
|
||||
#define BT_MAX_PROTO 8
|
||||
#define BT_MAX_PROTO (BTPROTO_LAST + 1)
|
||||
static const struct net_proto_family *bt_proto[BT_MAX_PROTO];
|
||||
static DEFINE_RWLOCK(bt_proto_lock);
|
||||
|
||||
@ -52,6 +52,7 @@ static const char *const bt_key_strings[BT_MAX_PROTO] = {
|
||||
"sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
|
||||
"sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
|
||||
"sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
|
||||
"sk_lock-AF_BLUETOOTH-BTPROTO_ISO",
|
||||
};
|
||||
|
||||
static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
|
||||
@ -64,6 +65,7 @@ static const char *const bt_slock_key_strings[BT_MAX_PROTO] = {
|
||||
"slock-AF_BLUETOOTH-BTPROTO_CMTP",
|
||||
"slock-AF_BLUETOOTH-BTPROTO_HIDP",
|
||||
"slock-AF_BLUETOOTH-BTPROTO_AVDTP",
|
||||
"slock-AF_BLUETOOTH-BTPROTO_ISO",
|
||||
};
|
||||
|
||||
void bt_sock_reclassify_lock(struct sock *sk, int proto)
|
||||
|
@ -3822,12 +3822,16 @@ static void hci_isodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
conn = hci_conn_hash_lookup_handle(hdev, handle);
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
/* TODO: Send to upper protocol */
|
||||
if (!conn) {
|
||||
bt_dev_err(hdev, "ISO packet for unknown connection handle %d",
|
||||
handle);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* Send to upper protocol */
|
||||
iso_recv(conn, skb, flags);
|
||||
return;
|
||||
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
1501
net/bluetooth/iso.c
Normal file
1501
net/bluetooth/iso.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -3985,10 +3985,16 @@ static const u8 rpa_resolution_uuid[16] = {
|
||||
0xea, 0x11, 0x73, 0xc2, 0x48, 0xa1, 0xc0, 0x15,
|
||||
};
|
||||
|
||||
/* 6fbaf188-05e0-496a-9885-d6ddfdb4e03e */
|
||||
static const u8 iso_socket_uuid[16] = {
|
||||
0x3e, 0xe0, 0xb4, 0xfd, 0xdd, 0xd6, 0x85, 0x98,
|
||||
0x6a, 0x49, 0xe0, 0x05, 0x88, 0xf1, 0xba, 0x6f,
|
||||
};
|
||||
|
||||
static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
|
||||
void *data, u16 data_len)
|
||||
{
|
||||
char buf[102]; /* Enough space for 5 features: 2 + 20 * 5 */
|
||||
char buf[122]; /* Enough space for 6 features: 2 + 20 * 6 */
|
||||
struct mgmt_rp_read_exp_features_info *rp = (void *)buf;
|
||||
u16 idx = 0;
|
||||
u32 flags;
|
||||
@ -4052,6 +4058,13 @@ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_LE)) {
|
||||
flags = iso_enabled() ? BIT(0) : 0;
|
||||
memcpy(rp->features[idx].uuid, iso_socket_uuid, 16);
|
||||
rp->features[idx].flags = cpu_to_le32(flags);
|
||||
idx++;
|
||||
}
|
||||
|
||||
rp->feature_count = cpu_to_le16(idx);
|
||||
|
||||
/* After reading the experimental features information, enable
|
||||
@ -4444,6 +4457,57 @@ static int set_le_simultaneous_roles_func(struct sock *sk, struct hci_dev *hdev,
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BT_LE
|
||||
static int set_iso_socket_func(struct sock *sk, struct hci_dev *hdev,
|
||||
struct mgmt_cp_set_exp_feature *cp, u16 data_len)
|
||||
{
|
||||
struct mgmt_rp_set_exp_feature rp;
|
||||
bool val, changed = false;
|
||||
int err;
|
||||
|
||||
/* Command requires to use the non-controller index */
|
||||
if (hdev)
|
||||
return mgmt_cmd_status(sk, hdev->id,
|
||||
MGMT_OP_SET_EXP_FEATURE,
|
||||
MGMT_STATUS_INVALID_INDEX);
|
||||
|
||||
/* Parameters are limited to a single octet */
|
||||
if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
|
||||
return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
|
||||
MGMT_OP_SET_EXP_FEATURE,
|
||||
MGMT_STATUS_INVALID_PARAMS);
|
||||
|
||||
/* Only boolean on/off is supported */
|
||||
if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
|
||||
return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
|
||||
MGMT_OP_SET_EXP_FEATURE,
|
||||
MGMT_STATUS_INVALID_PARAMS);
|
||||
|
||||
val = cp->param[0] ? true : false;
|
||||
if (val)
|
||||
err = iso_init();
|
||||
else
|
||||
err = iso_exit();
|
||||
|
||||
if (!err)
|
||||
changed = true;
|
||||
|
||||
memcpy(rp.uuid, iso_socket_uuid, 16);
|
||||
rp.flags = cpu_to_le32(val ? BIT(0) : 0);
|
||||
|
||||
hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
|
||||
|
||||
err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
|
||||
MGMT_OP_SET_EXP_FEATURE, 0,
|
||||
&rp, sizeof(rp));
|
||||
|
||||
if (changed)
|
||||
exp_feature_changed(hdev, iso_socket_uuid, val, sk);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct mgmt_exp_feature {
|
||||
const u8 *uuid;
|
||||
int (*set_func)(struct sock *sk, struct hci_dev *hdev,
|
||||
@ -4457,6 +4521,9 @@ static const struct mgmt_exp_feature {
|
||||
EXP_FEAT(quality_report_uuid, set_quality_report_func),
|
||||
EXP_FEAT(offload_codecs_uuid, set_offload_codec_func),
|
||||
EXP_FEAT(le_simultaneous_roles_uuid, set_le_simultaneous_roles_func),
|
||||
#ifdef CONFIG_BT_LE
|
||||
EXP_FEAT(iso_socket_uuid, set_iso_socket_func),
|
||||
#endif
|
||||
|
||||
/* end with a null feature */
|
||||
EXP_FEAT(NULL, NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user