mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Bluetooth: ISO: Fix not using bc_sid as advertisement SID
Currently bc_sid is being ignore when acting as Broadcast Source role,
so this fix it by passing the bc_sid and then use it when programming
the PA:
< HCI Command: LE Set Exte.. (0x08|0x0036) plen 25
Handle: 0x01
Properties: 0x0000
Min advertising interval: 140.000 msec (0x00e0)
Max advertising interval: 140.000 msec (0x00e0)
Channel map: 37, 38, 39 (0x07)
Own address type: Random (0x01)
Peer address type: Public (0x00)
Peer address: 00:00:00:00:00:00 (OUI 00-00-00)
Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00)
TX power: Host has no preference (0x7f)
Primary PHY: LE 1M (0x01)
Secondary max skip: 0x00
Secondary PHY: LE 2M (0x02)
SID: 0x01
Scan request notifications: Disabled (0x00)
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
@@ -242,6 +242,7 @@ struct adv_info {
|
||||
__u8 mesh;
|
||||
__u8 instance;
|
||||
__u8 handle;
|
||||
__u8 sid;
|
||||
__u32 flags;
|
||||
__u16 timeout;
|
||||
__u16 remaining_time;
|
||||
@@ -1551,13 +1552,14 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
||||
u16 timeout);
|
||||
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_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid,
|
||||
struct bt_iso_qos *qos,
|
||||
__u8 base_len, __u8 *base);
|
||||
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 dst_type, __u8 sid,
|
||||
struct bt_iso_qos *qos,
|
||||
__u8 data_len, __u8 *data);
|
||||
struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
__u8 dst_type, __u8 sid, struct bt_iso_qos *qos);
|
||||
@@ -1832,6 +1834,7 @@ 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_find_adv_sid(struct hci_dev *hdev, u8 sid);
|
||||
struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance);
|
||||
struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
|
||||
u32 flags, u16 adv_data_len, u8 *adv_data,
|
||||
@@ -1839,7 +1842,7 @@ struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
|
||||
u16 timeout, u16 duration, s8 tx_power,
|
||||
u32 min_interval, u32 max_interval,
|
||||
u8 mesh_handle);
|
||||
struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance,
|
||||
struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, u8 sid,
|
||||
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,
|
||||
|
||||
@@ -115,8 +115,8 @@ 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,
|
||||
int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 sid,
|
||||
u8 data_len, u8 *data, u32 flags, u16 min_interval,
|
||||
u16 max_interval, u16 sync_interval);
|
||||
|
||||
int hci_disable_per_advertising_sync(struct hci_dev *hdev, u8 instance);
|
||||
|
||||
@@ -1501,8 +1501,8 @@ static int qos_set_bis(struct hci_dev *hdev, struct bt_iso_qos *qos)
|
||||
|
||||
/* This function requires the caller holds hdev->lock */
|
||||
static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
struct bt_iso_qos *qos, __u8 base_len,
|
||||
__u8 *base)
|
||||
__u8 sid, struct bt_iso_qos *qos,
|
||||
__u8 base_len, __u8 *base)
|
||||
{
|
||||
struct hci_conn *conn;
|
||||
int err;
|
||||
@@ -1543,6 +1543,7 @@ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
return conn;
|
||||
|
||||
conn->state = BT_CONNECT;
|
||||
conn->sid = sid;
|
||||
|
||||
hci_conn_hold(conn);
|
||||
return conn;
|
||||
@@ -2062,7 +2063,8 @@ static int create_big_sync(struct hci_dev *hdev, void *data)
|
||||
if (qos->bcast.bis)
|
||||
sync_interval = interval * 4;
|
||||
|
||||
err = hci_start_per_adv_sync(hdev, qos->bcast.bis, conn->le_per_adv_data_len,
|
||||
err = hci_start_per_adv_sync(hdev, qos->bcast.bis, conn->sid,
|
||||
conn->le_per_adv_data_len,
|
||||
conn->le_per_adv_data, flags, interval,
|
||||
interval, sync_interval);
|
||||
if (err)
|
||||
@@ -2134,7 +2136,7 @@ static void create_big_complete(struct hci_dev *hdev, void *data, int err)
|
||||
}
|
||||
}
|
||||
|
||||
struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid,
|
||||
struct bt_iso_qos *qos,
|
||||
__u8 base_len, __u8 *base)
|
||||
{
|
||||
@@ -2156,7 +2158,7 @@ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
base, base_len);
|
||||
|
||||
/* We need hci_conn object using the BDADDR_ANY as dst */
|
||||
conn = hci_add_bis(hdev, dst, qos, base_len, eir);
|
||||
conn = hci_add_bis(hdev, dst, sid, qos, base_len, eir);
|
||||
if (IS_ERR(conn))
|
||||
return conn;
|
||||
|
||||
@@ -2207,20 +2209,35 @@ static void bis_mark_per_adv(struct hci_conn *conn, void *data)
|
||||
}
|
||||
|
||||
struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
__u8 dst_type, struct bt_iso_qos *qos,
|
||||
__u8 dst_type, __u8 sid,
|
||||
struct bt_iso_qos *qos,
|
||||
__u8 base_len, __u8 *base)
|
||||
{
|
||||
struct hci_conn *conn;
|
||||
int err;
|
||||
struct iso_list_data data;
|
||||
|
||||
conn = hci_bind_bis(hdev, dst, qos, base_len, base);
|
||||
conn = hci_bind_bis(hdev, dst, sid, qos, base_len, base);
|
||||
if (IS_ERR(conn))
|
||||
return conn;
|
||||
|
||||
if (conn->state == BT_CONNECTED)
|
||||
return conn;
|
||||
|
||||
/* Check if SID needs to be allocated then search for the first
|
||||
* available.
|
||||
*/
|
||||
if (conn->sid == HCI_SID_INVALID) {
|
||||
u8 sid;
|
||||
|
||||
for (sid = 0; sid <= 0x0f; sid++) {
|
||||
if (!hci_find_adv_sid(hdev, sid)) {
|
||||
conn->sid = sid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data.big = qos->bcast.big;
|
||||
data.bis = qos->bcast.bis;
|
||||
|
||||
|
||||
@@ -1584,6 +1584,19 @@ struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This function requires the caller holds hdev->lock */
|
||||
struct adv_info *hci_find_adv_sid(struct hci_dev *hdev, u8 sid)
|
||||
{
|
||||
struct adv_info *adv;
|
||||
|
||||
list_for_each_entry(adv, &hdev->adv_instances, list) {
|
||||
if (adv->sid == sid)
|
||||
return adv;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This function requires the caller holds hdev->lock */
|
||||
struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance)
|
||||
{
|
||||
@@ -1736,7 +1749,7 @@ struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
|
||||
}
|
||||
|
||||
/* This function requires the caller holds hdev->lock */
|
||||
struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance,
|
||||
struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, u8 sid,
|
||||
u32 flags, u8 data_len, u8 *data,
|
||||
u32 min_interval, u32 max_interval)
|
||||
{
|
||||
@@ -1748,6 +1761,7 @@ struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance,
|
||||
if (IS_ERR(adv))
|
||||
return adv;
|
||||
|
||||
adv->sid = sid;
|
||||
adv->periodic = true;
|
||||
adv->per_adv_data_len = data_len;
|
||||
|
||||
|
||||
@@ -1261,10 +1261,12 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance)
|
||||
hci_cpu_to_le24(adv->min_interval, cp.min_interval);
|
||||
hci_cpu_to_le24(adv->max_interval, cp.max_interval);
|
||||
cp.tx_power = adv->tx_power;
|
||||
cp.sid = adv->sid;
|
||||
} else {
|
||||
hci_cpu_to_le24(hdev->le_adv_min_interval, cp.min_interval);
|
||||
hci_cpu_to_le24(hdev->le_adv_max_interval, cp.max_interval);
|
||||
cp.tx_power = HCI_ADV_TX_POWER_NO_PREFERENCE;
|
||||
cp.sid = 0x00;
|
||||
}
|
||||
|
||||
secondary_adv = (flags & MGMT_ADV_FLAG_SEC_MASK);
|
||||
@@ -1594,8 +1596,8 @@ static int hci_adv_bcast_annoucement(struct hci_dev *hdev, struct adv_info *adv)
|
||||
return hci_update_adv_data_sync(hdev, adv->instance);
|
||||
}
|
||||
|
||||
int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
|
||||
u8 *data, u32 flags, u16 min_interval,
|
||||
int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 sid,
|
||||
u8 data_len, u8 *data, u32 flags, u16 min_interval,
|
||||
u16 max_interval, u16 sync_interval)
|
||||
{
|
||||
struct adv_info *adv = NULL;
|
||||
@@ -1607,6 +1609,18 @@ int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
|
||||
if (instance) {
|
||||
adv = hci_find_adv_instance(hdev, instance);
|
||||
if (adv) {
|
||||
if (sid != HCI_SID_INVALID && adv->sid != sid) {
|
||||
/* If the SID don't match attempt to find by
|
||||
* SID.
|
||||
*/
|
||||
adv = hci_find_adv_sid(hdev, sid);
|
||||
if (!adv) {
|
||||
bt_dev_err(hdev,
|
||||
"Unable to find adv_info");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Turn it into periodic advertising */
|
||||
adv->periodic = true;
|
||||
adv->per_adv_data_len = data_len;
|
||||
@@ -1615,7 +1629,7 @@ int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
|
||||
adv->flags = flags;
|
||||
} else if (!adv) {
|
||||
/* Create an instance if that could not be found */
|
||||
adv = hci_add_per_instance(hdev, instance, flags,
|
||||
adv = hci_add_per_instance(hdev, instance, sid, flags,
|
||||
data_len, data,
|
||||
sync_interval,
|
||||
sync_interval);
|
||||
|
||||
@@ -336,7 +336,7 @@ static int iso_connect_bis(struct sock *sk)
|
||||
struct hci_dev *hdev;
|
||||
int err;
|
||||
|
||||
BT_DBG("%pMR", &iso_pi(sk)->src);
|
||||
BT_DBG("%pMR (SID 0x%2.2x)", &iso_pi(sk)->src, iso_pi(sk)->bc_sid);
|
||||
|
||||
hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
|
||||
iso_pi(sk)->src_type);
|
||||
@@ -365,7 +365,7 @@ static int iso_connect_bis(struct sock *sk)
|
||||
|
||||
/* Just bind if DEFER_SETUP has been set */
|
||||
if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
|
||||
hcon = hci_bind_bis(hdev, &iso_pi(sk)->dst,
|
||||
hcon = hci_bind_bis(hdev, &iso_pi(sk)->dst, iso_pi(sk)->bc_sid,
|
||||
&iso_pi(sk)->qos, iso_pi(sk)->base_len,
|
||||
iso_pi(sk)->base);
|
||||
if (IS_ERR(hcon)) {
|
||||
@@ -375,12 +375,16 @@ static int iso_connect_bis(struct sock *sk)
|
||||
} else {
|
||||
hcon = hci_connect_bis(hdev, &iso_pi(sk)->dst,
|
||||
le_addr_type(iso_pi(sk)->dst_type),
|
||||
&iso_pi(sk)->qos, iso_pi(sk)->base_len,
|
||||
iso_pi(sk)->base);
|
||||
iso_pi(sk)->bc_sid, &iso_pi(sk)->qos,
|
||||
iso_pi(sk)->base_len, iso_pi(sk)->base);
|
||||
if (IS_ERR(hcon)) {
|
||||
err = PTR_ERR(hcon);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* Update SID if it was not set */
|
||||
if (iso_pi(sk)->bc_sid == HCI_SID_INVALID)
|
||||
iso_pi(sk)->bc_sid = hcon->sid;
|
||||
}
|
||||
|
||||
conn = iso_conn_add(hcon);
|
||||
|
||||
Reference in New Issue
Block a user