Commit eca0ae4a authored by Luiz Augusto von Dentz's avatar Luiz Augusto von Dentz
Browse files

Bluetooth: Add initial implementation of BIS connections



This adds initial support for BIS/BIG which includes:

== Broadcaster role: Setup a periodic advertising and create a BIG ==

> tools/isotest -s 00:00:00:00:00:00
isotest[63]: Connected [00:00:00:00:00:00]
isotest[63]: QoS BIG 0x00 BIS 0x00 Packing 0x00 Framing 0x00]
isotest[63]: Output QoS [Interval 10000 us Latency 10 ms SDU 40 PHY 0x02
RTN 2]
isotest[63]: Sending ...
isotest[63]: Number of packets: 1
isotest[63]: Socket jitter buffer: 80 buffer
< HCI Command: LE Set Perio.. (0x08|0x003e) plen 7
...
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Periodic Advertising Parameters (0x08|0x003e) ncmd 1
        Status: Success (0x00)
< HCI Command: LE Set Perio.. (0x08|0x003f) plen 7
...
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Periodic Advertising Data (0x08|0x003f) ncmd 1
        Status: Success (0x00)
< HCI Command: LE Set Perio.. (0x08|0x0040) plen 2
...
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Periodic Advertising Enable (0x08|0x0040) ncmd 1
        Status: Success (0x00)
< HCI Command: LE Create B.. (0x08|0x0068) plen 31
...
> HCI Event: Command Status (0x0f) plen 4
      LE Create Broadcast Isochronous Group (0x08|0x0068) ncmd 1
        Status: Success (0x00)
> HCI Event: LE Meta Event (0x3e) plen 21
      LE Broadcast Isochronous Group Complete (0x1b)
      ...

== Broadcast Receiver role: Create a PA Sync and BIG Sync ==

> tools/isotest -i hci1 -d 00:AA:01:00:00:00
isotest[66]: Waiting for connection 00:AA:01:00:00:00...
< HCI Command: LE Periodic Advert.. (0x08|0x0044) plen 14
...
> HCI Event: Command Status (0x0f) plen 4
      LE Periodic Advertising Create Sync (0x08|0x0044) ncmd 1
        Status: Success (0x00)
< HCI Command: LE Set Extended Sca.. (0x08|0x0041) plen 8
...
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Extended Scan Parameters (0x08|0x0041) ncmd 1
        Status: Success (0x00)
< HCI Command: LE Set Extended Sca.. (0x08|0x0042) plen 6
...
> HCI Event: Command Complete (0x0e) plen 4
      LE Set Extended Scan Enable (0x08|0x0042) ncmd 1
        Status: Success (0x00)
> HCI Event: LE Meta Event (0x3e) plen 29
      LE Extended Advertising Report (0x0d)
      ...
> HCI Event: LE Meta Event (0x3e) plen 16
      LE Periodic Advertising Sync Established (0x0e)
      ...
< HCI Command: LE Broadcast Isoch.. (0x08|0x006b) plen 25
...
> HCI Event: Command Status (0x0f) plen 4
      LE Broadcast Isochronous Group Create Sync (0x08|0x006b) ncmd 1
        Status: Success (0x00)
> HCI Event: LE Meta Event (0x3e) plen 17
      LE Broadcast Isochronous Group Sync Estabilished (0x1d)
      ...

Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent ccf74f23
Loading
Loading
Loading
Loading
+15 −3
Original line number Diff line number Diff line
@@ -160,6 +160,9 @@ struct bt_voice {
#define BT_ISO_QOS_CIG_UNSET	0xff
#define BT_ISO_QOS_CIS_UNSET	0xff

#define BT_ISO_QOS_BIG_UNSET	0xff
#define BT_ISO_QOS_BIS_UNSET	0xff

struct bt_iso_io_qos {
	__u32 interval;
	__u16 latency;
@@ -169,9 +172,18 @@ struct bt_iso_io_qos {
};

struct bt_iso_qos {
	union {
		__u8  cig;
		__u8  big;
	};
	union {
		__u8  cis;
		__u8  bis;
	};
	union {
		__u8  sca;
		__u8  sync_interval;
	};
	__u8  packing;
	__u8  framing;
	struct bt_iso_io_qos in;
+155 −7
Original line number Diff line number Diff line
@@ -316,6 +316,7 @@ enum {
	HCI_USER_CHANNEL,
	HCI_EXT_CONFIGURED,
	HCI_LE_ADV,
	HCI_LE_PER_ADV,
	HCI_LE_SCAN,
	HCI_SSP_ENABLED,
	HCI_SC_ENABLED,
@@ -338,6 +339,7 @@ enum {
	HCI_LE_SCAN_INTERRUPTED,
	HCI_WIDEBAND_SPEECH_ENABLED,
	HCI_EVENT_FILTER_CONFIGURED,
	HCI_PA_SYNC,

	HCI_DUT_MODE,
	HCI_VENDOR_DIAG,
@@ -519,9 +521,11 @@ enum {
#define HCI_LE_PHY_2M			0x01
#define HCI_LE_PHY_CODED		0x08
#define HCI_LE_EXT_ADV			0x10
#define HCI_LE_PERIODIC_ADV		0x20
#define HCI_LE_CHAN_SEL_ALG2		0x40
#define HCI_LE_CIS_CENTRAL		0x10
#define HCI_LE_CIS_PERIPHERAL		0x20
#define HCI_LE_ISO_BROADCASTER		0x40

/* Connection modes */
#define HCI_CM_ACTIVE	0x0000
@@ -1865,6 +1869,22 @@ struct hci_cp_le_ext_conn_param {
	__le16 max_ce_len;
} __packed;

#define HCI_OP_LE_PA_CREATE_SYNC	0x2044
struct hci_cp_le_pa_create_sync {
	__u8      options;
	__u8      sid;
	__u8      addr_type;
	bdaddr_t  addr;
	__le16    skip;
	__le16    sync_timeout;
	__u8      sync_cte_type;
} __packed;

#define HCI_OP_LE_PA_TERM_SYNC		0x2046
struct hci_cp_le_pa_term_sync {
	__le16    handle;
} __packed;

#define HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS	0x203b
struct hci_rp_le_read_num_supported_adv_sets {
	__u8  status;
@@ -1899,13 +1919,6 @@ struct hci_rp_le_set_ext_adv_params {
	__u8  tx_power;
} __packed;

#define HCI_OP_LE_SET_EXT_ADV_ENABLE		0x2039
struct hci_cp_le_set_ext_adv_enable {
	__u8  enable;
	__u8  num_of_sets;
	__u8  data[];
} __packed;

struct hci_cp_ext_adv_set {
	__u8  handle;
	__le16 duration;
@@ -1932,6 +1945,37 @@ struct hci_cp_le_set_ext_scan_rsp_data {
	__u8  data[];
} __packed;

#define HCI_OP_LE_SET_EXT_ADV_ENABLE		0x2039
struct hci_cp_le_set_ext_adv_enable {
	__u8  enable;
	__u8  num_of_sets;
	__u8  data[];
} __packed;

#define HCI_OP_LE_SET_PER_ADV_PARAMS		0x203e
struct hci_cp_le_set_per_adv_params {
	__u8      handle;
	__le16    min_interval;
	__le16    max_interval;
	__le16    periodic_properties;
} __packed;

#define HCI_MAX_PER_AD_LENGTH	252

#define HCI_OP_LE_SET_PER_ADV_DATA		0x203f
struct hci_cp_le_set_per_adv_data {
	__u8  handle;
	__u8  operation;
	__u8  length;
	__u8  data[];
} __packed;

#define HCI_OP_LE_SET_PER_ADV_ENABLE		0x2040
struct hci_cp_le_set_per_adv_enable {
	__u8  enable;
	__u8  handle;
} __packed;

#define LE_SET_ADV_DATA_OP_COMPLETE	0x03

#define LE_SET_ADV_DATA_NO_FRAG		0x01
@@ -2043,6 +2087,49 @@ struct hci_cp_le_reject_cis {
	__u8    reason;
} __packed;

#define HCI_OP_LE_CREATE_BIG			0x2068
struct hci_bis {
	__u8    sdu_interval[3];
	__le16  sdu;
	__le16  latency;
	__u8    rtn;
	__u8    phy;
	__u8    packing;
	__u8    framing;
	__u8    encryption;
	__u8    bcode[16];
} __packed;

struct hci_cp_le_create_big {
	__u8    handle;
	__u8    adv_handle;
	__u8    num_bis;
	struct hci_bis bis;
} __packed;

#define HCI_OP_LE_TERM_BIG			0x206a
struct hci_cp_le_term_big {
	__u8    handle;
	__u8    reason;
} __packed;

#define HCI_OP_LE_BIG_CREATE_SYNC		0x206b
struct hci_cp_le_big_create_sync {
	__u8    handle;
	__le16  sync_handle;
	__u8    encryption;
	__u8    bcode[16];
	__u8    mse;
	__le16  timeout;
	__u8    num_bis;
	__u8    bis[0];
} __packed;

#define HCI_OP_LE_BIG_TERM_SYNC			0x206c
struct hci_cp_le_big_term_sync {
	__u8    handle;
} __packed;

#define HCI_OP_LE_SETUP_ISO_PATH		0x206e
struct hci_cp_le_setup_iso_path {
	__le16  handle;
@@ -2595,6 +2682,18 @@ struct hci_ev_le_ext_adv_report {
	struct hci_ev_le_ext_adv_info info[];
} __packed;

#define HCI_EV_LE_PA_SYNC_ESTABLISHED	0x0e
struct hci_ev_le_pa_sync_established {
	__u8      status;
	__le16    handle;
	__u8      sid;
	__u8      bdaddr_type;
	bdaddr_t  bdaddr;
	__u8      phy;
	__le16    interval;
	__u8      clock_accuracy;
} __packed;

#define HCI_EV_LE_ENHANCED_CONN_COMPLETE    0x0a
struct hci_ev_le_enh_conn_complete {
	__u8      status;
@@ -2646,6 +2745,55 @@ struct hci_evt_le_cis_req {
	__u8  cis_id;
} __packed;

#define HCI_EVT_LE_CREATE_BIG_COMPLETE	0x1b
struct hci_evt_le_create_big_complete {
	__u8    status;
	__u8    handle;
	__u8    sync_delay[3];
	__u8    transport_delay[3];
	__u8    phy;
	__u8    nse;
	__u8    bn;
	__u8    pto;
	__u8    irc;
	__le16  max_pdu;
	__le16  interval;
	__u8    num_bis;
	__le16  bis_handle[];
} __packed;

#define HCI_EVT_LE_BIG_SYNC_ESTABILISHED 0x1d
struct hci_evt_le_big_sync_estabilished {
	__u8    status;
	__u8    handle;
	__u8    latency[3];
	__u8    nse;
	__u8    bn;
	__u8    pto;
	__u8    irc;
	__le16  max_pdu;
	__le16  interval;
	__u8    num_bis;
	__le16  bis[];
} __packed;

#define HCI_EVT_LE_BIG_INFO_ADV_REPORT	0x22
struct hci_evt_le_big_info_adv_report {
	__le16  sync_handle;
	__u8    num_bis;
	__u8    nse;
	__le16  iso_interval;
	__u8    bn;
	__u8    pto;
	__u8    irc;
	__le16  max_pdu;
	__u8    sdu_interval[3];
	__le16  max_sdu;
	__u8    phy;
	__u8    framing;
	__u8    encryption;
} __packed;

#define HCI_EV_VENDOR			0xff

/* Internal events generated by Bluetooth stack */
+80 −9
Original line number Diff line number Diff line
@@ -237,6 +237,7 @@ struct adv_info {
	struct list_head list;
	bool	enabled;
	bool	pending;
	bool	periodic;
	__u8	instance;
	__u32	flags;
	__u16	timeout;
@@ -248,6 +249,8 @@ struct adv_info {
	__u16	scan_rsp_len;
	__u8	scan_rsp_data[HCI_MAX_EXT_AD_LENGTH];
	bool	scan_rsp_changed;
	__u16	per_adv_data_len;
	__u8	per_adv_data[HCI_MAX_PER_AD_LENGTH];
	__s8	tx_power;
	__u32   min_interval;
	__u32   max_interval;
@@ -594,6 +597,8 @@ struct hci_dev {
	__u8			adv_data_len;
	__u8			scan_rsp_data[HCI_MAX_EXT_AD_LENGTH];
	__u8			scan_rsp_data_len;
	__u8			per_adv_data[HCI_MAX_PER_AD_LENGTH];
	__u8			per_adv_data_len;

	struct list_head	adv_instances;
	unsigned int		adv_instance_cnt;
@@ -679,6 +684,7 @@ struct hci_conn {
	__u8		resp_addr_type;
	__u8		adv_instance;
	__u16		handle;
	__u16		sync_handle;
	__u16		state;
	__u8		mode;
	__u8		type;
@@ -709,6 +715,8 @@ struct hci_conn {
	__u16		le_supv_timeout;
	__u8		le_adv_data[HCI_MAX_AD_LENGTH];
	__u8		le_adv_data_len;
	__u8		le_per_adv_data[HCI_MAX_PER_AD_LENGTH];
	__u8		le_per_adv_data_len;
	__u8		le_tx_phy;
	__u8		le_rx_phy;
	__s8		rssi;
@@ -942,6 +950,7 @@ enum {
	HCI_CONN_NEW_LINK_KEY,
	HCI_CONN_SCANNING,
	HCI_CONN_AUTH_FAILURE,
	HCI_CONN_PER_ADV,
};

static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
@@ -1060,6 +1069,29 @@ static inline __u8 hci_conn_lookup_type(struct hci_dev *hdev, __u16 handle)
	return type;
}

static inline struct hci_conn *hci_conn_hash_lookup_bis(struct hci_dev *hdev,
							bdaddr_t *ba,
							__u8 big, __u8 bis)
{
	struct hci_conn_hash *h = &hdev->conn_hash;
	struct hci_conn  *c;

	rcu_read_lock();

	list_for_each_entry_rcu(c, &h->list, list) {
		if (bacmp(&c->dst, ba) || c->type != ISO_LINK)
			continue;

		if (c->iso_qos.big == big && c->iso_qos.bis == bis) {
			rcu_read_unlock();
			return c;
		}
	}
	rcu_read_unlock();

	return NULL;
}

static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
								__u16 handle)
{
@@ -1170,6 +1202,29 @@ static inline struct hci_conn *hci_conn_hash_lookup_cig(struct hci_dev *hdev,
	return NULL;
}

static inline struct hci_conn *hci_conn_hash_lookup_big(struct hci_dev *hdev,
							__u8 handle)
{
	struct hci_conn_hash *h = &hdev->conn_hash;
	struct hci_conn  *c;

	rcu_read_lock();

	list_for_each_entry_rcu(c, &h->list, list) {
		if (bacmp(&c->dst, BDADDR_ANY) || c->type != ISO_LINK)
			continue;

		if (handle == c->iso_qos.big) {
			rcu_read_unlock();
			return c;
		}
	}

	rcu_read_unlock();

	return NULL;
}

static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
							__u8 type, __u16 state)
{
@@ -1264,6 +1319,13 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
			      __u8 dst_type, struct bt_iso_qos *qos);
struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
				 __u8 dst_type, struct bt_iso_qos *qos);
struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
				 __u8 dst_type, struct bt_iso_qos *qos,
				 __u8 data_len, __u8 *data);
int hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type,
		       __u8 sid);
int hci_le_big_create_sync(struct hci_dev *hdev, struct bt_iso_qos *qos,
			   __u16 sync_handle, __u8 num_bis, __u8 bis[]);
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,
@@ -1510,11 +1572,14 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
void hci_adv_instances_clear(struct hci_dev *hdev);
struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance);
struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance);
int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
			 u16 adv_data_len, u8 *adv_data,
struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
				      u32 flags, u16 adv_data_len, u8 *adv_data,
				      u16 scan_rsp_len, u8 *scan_rsp_data,
				      u16 timeout, u16 duration, s8 tx_power,
				      u32 min_interval, u32 max_interval);
struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance,
				      u32 flags, u8 data_len, u8 *data,
				      u32 min_interval, u32 max_interval);
int hci_set_adv_instance_data(struct hci_dev *hdev, u8 instance,
			 u16 adv_data_len, u8 *adv_data,
			 u16 scan_rsp_len, u8 *scan_rsp_data);
@@ -1631,14 +1696,18 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define use_enhanced_conn_complete(dev) (ll_privacy_capable(dev) || \
					 ext_adv_capable(dev))

/* CIS Master/Slave support */
#define iso_capable(dev) (cis_capable(dev))
/* Periodic advertising support */
#define per_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_PERIODIC_ADV))

/* CIS Master/Slave and BIS support */
#define iso_capable(dev) (cis_capable(dev) || bis_capable(dev))
#define cis_capable(dev) \
	(cis_central_capable(dev) || cis_peripheral_capable(dev))
#define cis_central_capable(dev) \
	((dev)->le_features[3] & HCI_LE_CIS_CENTRAL)
#define cis_peripheral_capable(dev) \
	((dev)->le_features[3] & HCI_LE_CIS_PERIPHERAL)
#define bis_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_BROADCASTER)

/* ----- HCI protocols ----- */
#define HCI_PROTO_DEFER             0x01
@@ -1926,6 +1995,8 @@ void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c);
#define DISCOV_LE_RESTART_DELAY		msecs_to_jiffies(200)	/* msec */
#define DISCOV_LE_FAST_ADV_INT_MIN	0x00A0	/* 100 msec */
#define DISCOV_LE_FAST_ADV_INT_MAX	0x00F0	/* 150 msec */
#define DISCOV_LE_PER_ADV_INT_MIN	0x00A0	/* 200 msec */
#define DISCOV_LE_PER_ADV_INT_MAX	0x00A0	/* 200 msec */

#define NAME_RESOLVE_DURATION		msecs_to_jiffies(10240)	/* 10.24 sec */

+11 −1
Original line number Diff line number Diff line
@@ -65,6 +65,10 @@ int hci_enable_ext_advertising_sync(struct hci_dev *hdev, u8 instance);
int hci_enable_advertising_sync(struct hci_dev *hdev);
int hci_enable_advertising(struct hci_dev *hdev);

int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
			   u8 *data, u32 flags, u16 min_interval,
			   u16 max_interval, u16 sync_interval);

int hci_remove_advertising_sync(struct hci_dev *hdev, struct sock *sk,
				u8 instance, bool force);
int hci_disable_advertising_sync(struct hci_dev *hdev);
@@ -83,6 +87,7 @@ int hci_update_scan(struct hci_dev *hdev);
int hci_write_le_host_supported_sync(struct hci_dev *hdev, u8 le, u8 simul);
int hci_remove_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance,
				     struct sock *sk);
int hci_remove_ext_adv_instance(struct hci_dev *hdev, u8 instance);
struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev, bool ext,
					     struct sock *sk);

@@ -111,4 +116,9 @@ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason);
int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn);

int hci_le_remove_cig_sync(struct hci_dev *hdev, u8 handle);
int hci_le_remove_cig(struct hci_dev *hdev, u8 handle);

int hci_le_terminate_big_sync(struct hci_dev *hdev, u8 handle, u8 reason);

int hci_le_big_terminate_sync(struct hci_dev *hdev, u8 handle);

int hci_le_pa_terminate_sync(struct hci_dev *hdev, u16 handle);
+21 −0
Original line number Diff line number Diff line
@@ -236,6 +236,27 @@ void eir_create(struct hci_dev *hdev, u8 *data)
	ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
}

u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
{
	struct adv_info *adv = NULL;
	u8 ad_len = 0;

	/* Return 0 when the current instance identifier is invalid. */
	if (instance) {
		adv = hci_find_adv_instance(hdev, instance);
		if (!adv)
			return 0;
	}

	if (adv) {
		memcpy(ptr, adv->per_adv_data, adv->per_adv_data_len);
		ad_len += adv->per_adv_data_len;
		ptr += adv->per_adv_data_len;
	}

	return ad_len;
}

u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
{
	struct adv_info *adv = NULL;
Loading