@@ -257,26 +257,43 @@ void bt_iso_cleanup(struct bt_conn *conn)
257257{
258258 int i ;
259259
260- if (conn -> iso .acl ) { /* CIS */
261- bt_conn_unref (conn -> iso .acl );
262- conn -> iso .acl = NULL ;
263-
264- /* Check if conn is last of CIG */
265- for (i = 0 ; i < CONFIG_BT_ISO_MAX_CHAN ; i ++ ) {
266- if (conn == & iso_conns [i ]) {
267- continue ;
268- }
260+ __ASSERT_NO_MSG (conn -> type == BT_CONN_TYPE_ISO );
269261
270- if (atomic_get (& iso_conns [i ].ref ) &&
271- iso_conns [i ].iso .cig_id == conn -> iso .cig_id ) {
272- break ;
273- }
262+ BT_DBG ("%p" , conn );
263+
264+ /* Check if ISO connection is in fact a BIS */
265+ if (!conn -> iso .acl ) {
266+ goto done ;
267+ }
268+
269+ /* If ACL is still connected there are channels to serve that means the
270+ * connection is still in use.
271+ */
272+ if (conn -> iso .acl -> state == BT_CONN_CONNECTED &&
273+ !sys_slist_is_empty (& conn -> channels )) {
274+ goto done ;
275+ }
276+
277+ bt_conn_unref (conn -> iso .acl );
278+ conn -> iso .acl = NULL ;
279+
280+ /* Check if conn is last of CIG */
281+ for (i = 0 ; i < CONFIG_BT_ISO_MAX_CHAN ; i ++ ) {
282+ if (conn == & iso_conns [i ]) {
283+ continue ;
274284 }
275285
276- if (i == CONFIG_BT_ISO_MAX_CHAN ) {
277- hci_le_remove_cig (conn -> iso .cig_id );
286+ if (atomic_get (& iso_conns [i ].ref ) &&
287+ iso_conns [i ].iso .cig_id == conn -> iso .cig_id ) {
288+ break ;
278289 }
279290 }
291+
292+ if (i == CONFIG_BT_ISO_MAX_CHAN ) {
293+ hci_le_remove_cig (conn -> iso .cig_id );
294+ }
295+
296+ done :
280297 bt_conn_unref (conn );
281298}
282299
@@ -734,23 +751,25 @@ static void bt_iso_remove_data_path(struct bt_conn *conn)
734751 hci_le_remove_iso_data_path (conn , BT_HCI_DATAPATH_DIR_HOST_TO_CTLR );
735752}
736753
737- static void bt_iso_chan_del (struct bt_iso_chan * chan )
754+ static void bt_iso_chan_disconnected (struct bt_iso_chan * chan )
738755{
739756 BT_DBG ("%p" , chan );
740757
741758 if (!chan -> conn ) {
742- goto done ;
759+ bt_iso_chan_set_state (chan , BT_ISO_DISCONNECTED );
760+ return ;
761+ }
762+
763+ bt_iso_chan_set_state (chan , BT_ISO_BOUND );
764+
765+ /* Unbind if acting as slave */
766+ if (chan -> conn -> role == BT_HCI_ROLE_SLAVE ) {
767+ bt_iso_chan_unbind (chan );
743768 }
744769
745770 if (chan -> ops -> disconnected ) {
746771 chan -> ops -> disconnected (chan );
747772 }
748-
749- bt_conn_unref (chan -> conn );
750- chan -> conn = NULL ;
751-
752- done :
753- bt_iso_chan_set_state (chan , BT_ISO_DISCONNECTED );
754773}
755774
756775void bt_iso_disconnected (struct bt_conn * conn )
@@ -768,7 +787,7 @@ void bt_iso_disconnected(struct bt_conn *conn)
768787 bt_iso_remove_data_path (conn );
769788
770789 SYS_SLIST_FOR_EACH_CONTAINER_SAFE (& conn -> channels , chan , next , node ) {
771- bt_iso_chan_del (chan );
790+ bt_iso_chan_disconnected (chan );
772791 }
773792}
774793
@@ -832,12 +851,8 @@ void bt_iso_chan_set_state_debug(struct bt_iso_chan *chan, uint8_t state,
832851 /* check transitions validness */
833852 switch (state ) {
834853 case BT_ISO_DISCONNECTED :
835- /* regardless of old state always allows this state */
836- break ;
837854 case BT_ISO_BOUND :
838- if (chan -> state != BT_ISO_DISCONNECTED ) {
839- BT_WARN ("%s()%d: invalid transition" , func , line );
840- }
855+ /* regardless of old state always allows these states */
841856 break ;
842857 case BT_ISO_CONNECT :
843858 if (chan -> state != BT_ISO_BOUND ) {
@@ -916,6 +931,24 @@ int bt_iso_chan_bind(struct bt_conn **conns, uint8_t num_conns,
916931 return 0 ;
917932}
918933
934+ int bt_iso_chan_unbind (struct bt_iso_chan * chan )
935+ {
936+ __ASSERT_NO_MSG (chan );
937+
938+ if (!chan -> conn || chan -> state != BT_ISO_BOUND ) {
939+ return - EINVAL ;
940+ }
941+
942+ bt_iso_chan_remove (chan -> conn , chan );
943+
944+ bt_conn_unref (chan -> conn );
945+ chan -> conn = NULL ;
946+
947+ bt_iso_chan_set_state (chan , BT_ISO_DISCONNECTED );
948+
949+ return 0 ;
950+ }
951+
919952int bt_iso_chan_connect (struct bt_iso_chan * * chans , uint8_t num_chans )
920953{
921954 struct bt_conn * conns [CONFIG_BT_ISO_MAX_CHAN ];
@@ -954,7 +987,7 @@ int bt_iso_chan_disconnect(struct bt_iso_chan *chan)
954987
955988 if (chan -> state == BT_ISO_BOUND ) {
956989 bt_iso_chan_remove (chan -> conn , chan );
957- bt_iso_chan_del (chan );
990+ bt_iso_chan_disconnected (chan );
958991 return 0 ;
959992 }
960993
0 commit comments