diff mbox series

Bluetooth: hci_conn: Fix CIS connection dst_type handling

Message ID 20221009174216.17533-1-pav@iki.fi
State New
Headers show
Series Bluetooth: hci_conn: Fix CIS connection dst_type handling | expand

Commit Message

Pauli Virtanen Oct. 9, 2022, 5:42 p.m. UTC
hci_connect_cis and iso_connect_cis call hci_bind_cis inconsistently
with dst_type being either ISO socket address type or the HCI type, but
these values cannot be mixed like this. Fix this by using only the
socket address type.

CIS connection dst_type was also not initialized in hci_bind_cis, even
though it is used in hci_conn_hash_lookup_cis to find existing
connections.  Set the value in hci_bind_cis, so that existing CIS
connections are found e.g. when doing deferred socket connections, also
when dst_type is not 0 (ADDR_LE_DEV_PUBLIC).

Fixes: 26afbd826ee3 ("Bluetooth: Add initial implementation of CIS connections")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
---

Notes:
    I've been playing with the LE Audio bits with Pipewire, and ran into
    a problem in connecting to nrf5340 devkit running its example
    application, which presumably is supposed to work.
    
    Everything works up to trying to acquire the BlueZ transport, which
    fails in BlueZ profiles/audio/bap.c:bap_accept_io where read() from the
    socket returns EINVAL.
    
    Adding some debug prints in kernel side shows that this occurs in
    
    net/bluetooth/iso.c:iso_sock_recvmsg ->
    net/bluetooth/iso.c:iso_connect_cis ->
    net/bluetooth/hci_conn.c:hci_bind_cis
    
    At this point, the CIS connection to the device already exists, but
    hci_conn_hash_lookup_cis fails to find it, because hci_conn->dst_type in
    the connection list does not match the dst_type passed to hci_bind_cis.
    Since it does not find existing connection, it tries to create a new
    one, which fails in hci_le_set_cig_params in the if (qos->cis !=
    BT_ISO_QOS_CIS_UNSET) branch, because the same CIS id is already
    reserved.
    
    It appears the dst_type field of CIS hci_conn is never initialized, so
    it happens to work for dst_type being ADDR_LE_DEV_PUBLIC (0) but not in
    other cases. In the case with the devkit, it's ADDR_LE_DEV_RANDOM.
    
    iso_connect_cis also calls hci_bind_cis directly with
    iso_pi(sk)->dst_type, which is BDADDR_LE_* value, not ADDR_LE_DEV_*
    value like it is when hci_bind_cis is called from hci_connect_cis.
    
    The patch here attempts to address these.  With this, sound comes out
    from the remote device fine, but I'm not familiar with the code here, so
    caveat emptor...
    
    Logs for reference (on v6.0, without this patch, with some extra BT_DBG added):
    
    bluetoothd[5349]: profiles/audio/bap.c:bap_connect_io() ep 0x60b0000392a0 stream 0x60b000039a30 defer true
    kernel: sock 000000002255c62a
    kernel: sk 0000000056fe6d75
    kernel: sk 0000000056fe6d75 84:5c:f3:52:11:91 type 1
    kernel: sk 0000000056fe6d75
    kernel: sk 0000000056fe6d75
    kernel: iso_sock_connect: sk 0000000056fe6d75
    kernel: iso_connect_cis: 84:5c:f3:52:11:91 -> c8:3d:d1:fe:ca:67, dst_type:2
    kernel: 84:5c:f3:52:11:91 -> c8:3d:d1:fe:ca:67
    kernel: hci0 orig refcnt 11
    kernel: hci0 hci_bind_cis: dst:c8:3d:d1:fe:ca:67 dst_type:2
    kernel: hci0 hci_bind_cis: new cis
    kernel: hci0 dst c8:3d:d1:fe:ca:67
    kernel: hci0 orig refcnt 12
    kernel: 00000000ece7f209 hci_le_set_cig_params
    kernel: hcon 00000000ece7f209 conn 00000000f0fe860f
    kernel: conn 00000000f0fe860f
    kernel: sock 0000000056fe6d75 state 3
    kernel: iso_connect_cis: ret:0
    kernel: hci0 orig refcnt 13
    kernel: iso_sock_connect: sk 0000000056fe6d75 ret:0
    kernel: sk 0000000056fe6d75
    kernel: sock 000000002255c62a, sk 0000000056fe6d75
    kernel: sock 000000002255c62a, sk 0000000056fe6d75
    kernel: hci0: event 0x0e
    kernel: hci0: opcode 0x2062
    kernel: hci0: status 0x00
    kernel: hci0: 00000000ece7f209 handle 0x0a00 link 0000000000000000
    bluetoothd[5349]: profiles/audio/bap.c:bap_connect_io() bt_io: connect: ep:0x60b0000392a0
    bluetoothd[5349]: profiles/audio/bap.c:bap_connect_io() bt_io: connect -> io:0x60c000015ac0 fd:32
    bluetoothd[5349]: src/shared/bap.c:bap_stream_io_attach() stream 0x60b000039a30 connecting true
    bluetoothd[5349]: src/shared/bap.c:stream_io_new() fd 32
    bluetoothd[5349]: profiles/audio/bap.c:bap_connecting() stream 0x60b000039a30 fd 32: CIG 0x00 CIS 0x00
    bluetoothd[5349]: src/shared/bap.c:bap_queue_req() req 0x606000017fc0 (op 0x02) queue 0x6030000
    bluetoothd[5349]: profiles/gap/gas.c:read_device_name_cb() GAP Device Name: NRF5340_AUDIO
    kernel: hci0: event 0x13
    kernel: hci0: num 1
    kernel: hcon 000000002dae917f mode 0
    kernel: hci0: event 0x3e
    kernel: hci0: subevent 0x07
    kernel: hci0: event 0x13
    kernel: hci0: num 1
    bluetoothd[5349]: src/shared/att.c:can_read_data() (chan 0x607000008bb0) ATT PDU received: 0x1b
    bluetoothd[5349]: profiles/audio/bap.c:qos_cb() stream 0x60b000039a30 code 0x00 reason 0x00
    kernel: hcon 000000002dae917f mode 0
    kernel: hcon 000000002dae917f mode 0
    kernel: hci0: event 0x13
    kernel: hci0: num 1
    kernel: hcon 000000002dae917f mode 0
    bluetoothd[5349]: src/shared/att.c:can_read_data() (chan 0x607000008bb0) ATT PDU received: 0x1b
    bluetoothd[5349]: src/shared/bap.c:bap_ep_set_status() ASE status: ep 0x603000026980 id 0x01 ha
    bluetoothd[5349]: src/shared/bap.c:ep_status_qos() CIG 0x00 CIS 0x00 interval 10000 framing 0x0
    bluetoothd[5349]: profiles/audio/media.c:pac_config() endpoint 0x60d000000860 path /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/pac_sink0
    bluetoothd[5349]: profiles/audio/media.c:media_endpoint_async_call() Calling SetConfiguration: name = :1.146 path = /MediaEndpoint/BAPSource/lc3
    bluetoothd[5349]: src/shared/bap.c:bap_stream_state_changed() stream 0x60b000039a30 dir 0x01: c
    bluetoothd[5349]: src/shared/bap.c:bap_stream_update_io_links() stream 0x60b000039a30
    bluetoothd[5349]: profiles/audio/bap.c:bap_state() stream 0x60b000039a30: config(1) -> qos(2)
    bluetoothd[5349]: profiles/audio/bap.c:bap_create_io() ep 0x60b0000392a0 stream 0x60b000039a30 defer true
    bluetoothd[5349]: src/shared/bap.c:bt_bap_stream_io_get_qos() in (nil) out 0x60b000039a68
    bluetoothd[5349]: profiles/audio/transport.c:bap_state_changed() stream 0x60b000039a30: config(1) -> qos(2)
    bluetoothd[5349]: profiles/audio/transport.c:transport_update_playing() /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/pac_sink0/fd0 State=TRANSPORT_STATE_IDLE Playing=0
    bluetoothd[5349]: profiles/gap/gas.c:read_appearance_cb() GAP Appearance: 0x0000
    kernel: hci0: event 0x13
    kernel: hci0: num 1
    kernel: hcon 000000002dae917f mode 0
    kernel: hci0: event 0x13
    kernel: hci0: num 1
    kernel: hcon 000000002dae917f mode 0
    kernel: hci0: event 0x13
    kernel: hci0: num 1
    bluetoothd[5349]: src/shared/gatt-client.c:db_hash_read_cb() DB Hash found: handle 0x0008 lengt
    bluetoothd[5349]: src/shared/gatt-client.c:db_hash_read_cb() DB Hash match: skipping discovery
    bluetoothd[5349]: src/shared/gatt-client.c:write_client_features() Writing Client Features 0x05
    bluetoothd[5349]: src/device.c:gatt_client_ready_cb() status: success, error: 0
    bluetoothd[5349]: src/gatt-client.c:btd_gatt_client_ready() GATT client ready
    kernel: hcon 000000002dae917f mode 0
    bluetoothd[5349]: src/gatt-client.c:create_services() Exporting objects for GATT services: C8:3D:D1:FE:CA:67
    bluetoothd[5349]: src/gatt-client.c:service_create() Exported GATT service: /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/service0001
    bluetoothd[5349]: src/gatt-client.c:characteristic_create() Exported GATT characteristic: /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/service0001/char0002
    bluetoothd[5349]: src/gatt-client.c:descriptor_create() Exported GATT characteristic descriptor: /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/service0001/char0002/desc0004
    bluetoothd[5349]: src/gatt-client.c:characteristic_create() Exported GATT characteristic: /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/service0001/char0005
    bluetoothd[5349]: src/gatt-client.c:characteristic_create() Exported GATT characteristic: /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/service0001/char0007
    bluetoothd[5349]: src/gatt-client.c:service_create() Exported GATT service: /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/service0022
    bluetoothd[5349]: src/gatt-client.c:characteristic_create() Exported GATT characteristic: /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/service0022/char0023
    bluetoothd[5349]: src/gatt-client.c:descriptor_create() Exported GATT characteristic descriptor: /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/service0022/char0023/desc0025
    bluetoothd[5349]: src/gatt-client.c:characteristic_create() Exported GATT characteristic: /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/service0022/char0026
    bluetoothd[5349]: src/gatt-client.c:characteristic_create() Exported GATT characteristic: /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/service0022/char0028
    bluetoothd[5349]: src/gatt-client.c:descriptor_create() Exported GATT characteristic descriptor: /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/service0022/char0028/desc002a
    bluetoothd[5349]: src/gatt-client.c:btd_gatt_client_ready() Features 0x00
    bluetoothd[5349]: src/gatt-client.c:btd_gatt_client_ready() Update Features 0x05
    bluetoothd[5349]: src/device.c:device_svc_resolved() /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67 err 0
    kernel: hci0: event 0x13
    kernel: hci0: num 1
    kernel: hcon 000000002dae917f mode 0
    kernel: hci0: event 0x13
    kernel: hci0: num 1
    bluetoothd[5349]: src/shared/gatt-client.c:service_changed_register_cb() Registered handler for
    kernel: hcon 000000002dae917f mode 0
    bluetoothd[5349]: profiles/audio/transport.c:media_owner_create() Owner created: sender=:1.146
    bluetoothd[5349]: src/shared/bap.c:bap_queue_req() req 0x60600001cee0 (op 0x03) queue 0x6030000
    bluetoothd[5349]: profiles/audio/transport.c:transport_set_state() State changed /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/pac_sink0/fd0: TRANSPORT_STATE_IDLE -> TRANSPORT_STATE_REQUESTING
    bluetoothd[5349]: profiles/audio/transport.c:media_request_create() Request created: method=Acquire id=3
    bluetoothd[5349]: profiles/audio/transport.c:media_owner_add() Owner :1.146 Request Acquire
    bluetoothd[5349]: profiles/audio/transport.c:media_transport_set_owner() Transport /org/bluez/hci0/dev_C8_3D_D1_FE_CA_67/pac_sink0/fd0 Owner :1.146
    kernel: hci0: event 0x13
    kernel: hci0: num 1
    bluetoothd[5349]: src/shared/att.c:can_read_data() (chan 0x607000008bb0) ATT PDU received: 0x1b
    kernel: hcon 000000002dae917f mode 0
    kernel: hcon 000000002dae917f mode 0
    bluetoothd[5349]: src/shared/att.c:can_read_data() (chan 0x607000008bb0) ATT PDU received: 0x1b
    bluetoothd[5349]: src/shared/bap.c:bap_ep_set_status() ASE status: ep 0x603000026980 id 0x01 ha
    bluetoothd[5349]: src/shared/bap.c:ep_status_metadata() CIS 0x00 CIG 0x00 metadata len 4
    bluetoothd[5349]: src/shared/bap.c:bap_stream_state_changed() stream 0x60b000039a30 dir 0x01: q
    bluetoothd[5349]: profiles/audio/bap.c:bap_state() stream 0x60b000039a30: qos(2) -> enabling(3)
    bluetoothd[5349]: profiles/audio/bap.c:bap_create_io() ep 0x60b0000392a0 stream 0x60b000039a30 defer false
    bluetoothd[5349]: src/shared/bap.c:bt_bap_stream_io_get_qos() in (nil) out 0x60b000039a68
    bluetoothd[5349]: profiles/audio/bap.c:bap_accept_io() stream 0x60b000039a30 fd 32 defer true
    kernel: sk 0000000056fe6d75
    kernel: iso_sock_recvmsg: sk 0000000056fe6d75
    kernel: iso_sock_recvmsg: defer connect 0000000056fe6d75
    kernel: iso_connect_cis: 84:5c:f3:52:11:91 -> c8:3d:d1:fe:ca:67, dst_type:2
    kernel: 84:5c:f3:52:11:91 -> c8:3d:d1:fe:ca:67
    kernel: hci0 orig refcnt 12
    kernel: hci0 hci_connect_cis: dst:c8:3d:d1:fe:ca:67 dst_type:2
    kernel: hcon 000000002dae917f orig refcnt 1
    kernel: hci0 hci_bind_cis: dst:c8:3d:d1:fe:ca:67 dst_type:1
    kernel: hci0 hci_conn_hash_lookup_cis: c:00000000ece7f209 c->dst:c8:3d:d1:fe:ca:67 c->dst_type:0 ba:c8:3d:d1:fe:ca:67 ba_type:1
    kernel: hci0 hci_bind_cis: new cis
    kernel: hci0 dst c8:3d:d1:fe:ca:67
    kernel: hci0 orig refcnt 13
    kernel: 00000000c554a79d hci_le_set_cig_params
    kernel: 00000000ece7f209 cis_list: cig:0 cis:0 vs. d->cig:0, d->cis:0
    kernel: 00000000ece7f209 cis_list: MATCH
    kernel: hci0 hci_le_set_cig_params: ERROR: cig:0, cis:0 already exists
    kernel: hci0 hci_bind_cis: ERROR: hci_le_set_cig_params
    kernel: hcon 00000000c554a79d orig refcnt 0
    kernel: hcon 000000002dae917f orig refcnt 2
    kernel: iso_connect_cis: ret:-22
    kernel: hci0 orig refcnt 14
    kernel: sock 000000002255c62a, sk 0000000056fe6d75
    kernel: sock 0000000056fe6d75 state 5
    kernel: sk 0000000056fe6d75 state 5 socket 000000002255c62a
    kernel: sk 0000000056fe6d75, conn 00000000f0fe860f, err 104
    kernel: hcon 00000000ece7f209 orig refcnt 0
    bluetoothd[5349]: profiles/audio/bap.c:bap_accept_io() read: Invalid argument (22)

 net/bluetooth/hci_conn.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

Comments

Pauli Virtanen Oct. 10, 2022, 7:08 p.m. UTC | #1
Hi Luiz,

su, 2022-10-09 kello 14:45 -0700, Luiz Augusto von Dentz kirjoitti:
[clip]
> > diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> > index 9777e7b109ee..78d8b8b7fd72 100644
> > --- a/net/bluetooth/hci_conn.c
> > +++ b/net/bluetooth/hci_conn.c
> > @@ -1691,12 +1691,19 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
> >  {
> >         struct hci_conn *cis;
> > 
> > +       /* Convert from ISO socket address type to HCI address type  */
> > +       if (dst_type == BDADDR_LE_PUBLIC)
> > +               dst_type = ADDR_LE_DEV_PUBLIC;
> > +       else
> > +               dst_type = ADDR_LE_DEV_RANDOM;
> > +
> >         cis = hci_conn_hash_lookup_cis(hdev, dst, dst_type);
> >         if (!cis) {
> >                 cis = hci_conn_add(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
> >                 if (!cis)
> >                         return ERR_PTR(-ENOMEM);
> >                 cis->cleanup = cis_cleanup;
> > +               cis->dst_type = dst_type;
> >         }
> > 
> >         if (cis->state == BT_CONNECTED)
> > @@ -2075,20 +2082,21 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
> >  {
> >         struct hci_conn *le;
> >         struct hci_conn *cis;
> > +       u8 hci_dst_type;
> > 
> >         /* Convert from ISO socket address type to HCI address type  */
> >         if (dst_type == BDADDR_LE_PUBLIC)
> > -               dst_type = ADDR_LE_DEV_PUBLIC;
> > +               hci_dst_type = ADDR_LE_DEV_PUBLIC;
> >         else
> > -               dst_type = ADDR_LE_DEV_RANDOM;
> > +               hci_dst_type = ADDR_LE_DEV_RANDOM;
> 
> Nice catch, though I think we should make sure these types are not
> from hci_conn.c as the name suggest these should be dealing HCI
> procedures so it doesn't make much sense to propagate types other than
> HCI.

Not sure I parse right: You want to move the conversions to the
callsite in iso.c? Or change the variable name here? If the former,
there are a few other instances of these in hci_conn.c.

> >         if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
> > -               le = hci_connect_le(hdev, dst, dst_type, false,
> > +               le = hci_connect_le(hdev, dst, hci_dst_type, false,
> >                                     BT_SECURITY_LOW,
> >                                     HCI_LE_CONN_TIMEOUT,
> >                                     HCI_ROLE_SLAVE);
> >         else
> > -               le = hci_connect_le_scan(hdev, dst, dst_type,
> > +               le = hci_connect_le_scan(hdev, dst, hci_dst_type,
> >                                          BT_SECURITY_LOW,
> >                                          HCI_LE_CONN_TIMEOUT,
> >                                          CONN_REASON_ISO_CONNECT);
> > --
> > 2.37.3
> > 
> 
> While at it probably makes sense to introduce a test to iso-tester
> that uses random address rather than always using public, that way we
> can make sure we exercise this code with CI.
patchwork-bot+bluetooth@kernel.org Oct. 11, 2022, 8:50 p.m. UTC | #2
Hello:

This series was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Sun,  9 Oct 2022 20:42:15 +0300 you wrote:
> hci_connect_cis and iso_connect_cis call hci_bind_cis inconsistently
> with dst_type being either ISO socket address type or the HCI type, but
> these values cannot be mixed like this. Fix this by using only the
> socket address type.
> 
> CIS connection dst_type was also not initialized in hci_bind_cis, even
> though it is used in hci_conn_hash_lookup_cis to find existing
> connections.  Set the value in hci_bind_cis, so that existing CIS
> connections are found e.g. when doing deferred socket connections, also
> when dst_type is not 0 (ADDR_LE_DEV_PUBLIC).
> 
> [...]

Here is the summary with links:
  - Bluetooth: hci_conn: Fix CIS connection dst_type handling
    (no matching commit)
  - [v2,2/2] Bluetooth: hci_conn: use HCI dst_type values also for BIS
    https://git.kernel.org/bluetooth/bluetooth-next/c/4d12cd187c82

You are awesome, thank you!
diff mbox series

Patch

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 9777e7b109ee..78d8b8b7fd72 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1691,12 +1691,19 @@  struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
 {
 	struct hci_conn *cis;
 
+	/* Convert from ISO socket address type to HCI address type  */
+	if (dst_type == BDADDR_LE_PUBLIC)
+		dst_type = ADDR_LE_DEV_PUBLIC;
+	else
+		dst_type = ADDR_LE_DEV_RANDOM;
+
 	cis = hci_conn_hash_lookup_cis(hdev, dst, dst_type);
 	if (!cis) {
 		cis = hci_conn_add(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
 		if (!cis)
 			return ERR_PTR(-ENOMEM);
 		cis->cleanup = cis_cleanup;
+		cis->dst_type = dst_type;
 	}
 
 	if (cis->state == BT_CONNECTED)
@@ -2075,20 +2082,21 @@  struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
 {
 	struct hci_conn *le;
 	struct hci_conn *cis;
+	u8 hci_dst_type;
 
 	/* Convert from ISO socket address type to HCI address type  */
 	if (dst_type == BDADDR_LE_PUBLIC)
-		dst_type = ADDR_LE_DEV_PUBLIC;
+		hci_dst_type = ADDR_LE_DEV_PUBLIC;
 	else
-		dst_type = ADDR_LE_DEV_RANDOM;
+		hci_dst_type = ADDR_LE_DEV_RANDOM;
 
 	if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
-		le = hci_connect_le(hdev, dst, dst_type, false,
+		le = hci_connect_le(hdev, dst, hci_dst_type, false,
 				    BT_SECURITY_LOW,
 				    HCI_LE_CONN_TIMEOUT,
 				    HCI_ROLE_SLAVE);
 	else
-		le = hci_connect_le_scan(hdev, dst, dst_type,
+		le = hci_connect_le_scan(hdev, dst, hci_dst_type,
 					 BT_SECURITY_LOW,
 					 HCI_LE_CONN_TIMEOUT,
 					 CONN_REASON_ISO_CONNECT);