@@ -2110,25 +2110,19 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
return;
}
- if (bt_bap_stream_get_type(stream) ==
- BT_BAP_STREAM_TYPE_UCAST) {
- /* Wait QoS response to respond */
- setup->id = bt_bap_stream_qos(stream,
- &setup->qos,
- qos_cb, setup);
- if (!setup->id) {
- error("Failed to Configure QoS");
- bt_bap_stream_release(stream,
- NULL, NULL);
- }
+ /* Wait QoS response to respond */
+ setup->id = bt_bap_stream_qos(stream,
+ &setup->qos,
+ qos_cb, setup);
+ if (!setup->id) {
+ error("Failed to Configure QoS");
+ bt_bap_stream_release(stream,
+ NULL, NULL);
}
}
break;
case BT_BAP_STREAM_STATE_QOS:
- if (bt_bap_stream_get_type(stream) ==
- BT_BAP_STREAM_TYPE_UCAST) {
setup_create_io(data, setup, stream, true);
- }
break;
case BT_BAP_STREAM_STATE_ENABLING:
if (setup)
@@ -2139,6 +2133,45 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
}
}
+static void bap_state_bcast(struct bt_bap_stream *stream, uint8_t old_state,
+ uint8_t new_state, void *user_data)
+{
+ struct bap_data *data = user_data;
+ struct bap_setup *setup;
+
+ DBG("stream %p: %s(%u) -> %s(%u)", stream,
+ bt_bap_stream_statestr(old_state), old_state,
+ bt_bap_stream_statestr(new_state), new_state);
+
+ /* Ignore transitions back to same state */
+ if (new_state == old_state)
+ return;
+
+ setup = bap_find_setup_by_stream(data, stream);
+
+ switch (new_state) {
+ case BT_BAP_STREAM_STATE_IDLE:
+ /* Release stream if idle */
+ if (setup)
+ setup_free(setup);
+ else
+ queue_remove(data->streams, stream);
+ break;
+ case BT_BAP_STREAM_STATE_CONFIG:
+ if (setup && !setup->id) {
+ setup_create_io(data, setup, stream, true);
+ if (!setup->io) {
+ error("Unable to create io");
+ if (old_state != BT_BAP_STREAM_STATE_RELEASING)
+ bt_bap_stream_release(stream, NULL,
+ NULL);
+ return;
+ }
+ }
+ break;
+ }
+}
+
static void pac_added(struct bt_bap_pac *pac, void *user_data)
{
struct btd_service *service = user_data;
@@ -2332,45 +2365,69 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
g_io_channel_set_close_on_unref(io, FALSE);
- switch (bt_bap_stream_get_type(setup->stream)) {
- case BT_BAP_STREAM_TYPE_UCAST:
- /* Attempt to get CIG/CIS if they have not been set */
- if (qos->ucast.cig_id == BT_ISO_QOS_CIG_UNSET ||
- qos->ucast.cis_id == BT_ISO_QOS_CIS_UNSET) {
- struct bt_iso_qos iso_qos;
+ /* Attempt to get CIG/CIS if they have not been set */
+ if (qos->ucast.cig_id == BT_ISO_QOS_CIG_UNSET ||
+ qos->ucast.cis_id == BT_ISO_QOS_CIS_UNSET) {
+ struct bt_iso_qos iso_qos;
- if (!io_get_qos(io, &iso_qos)) {
- g_io_channel_unref(io);
- return;
- }
-
- qos->ucast.cig_id = iso_qos.ucast.cig;
- qos->ucast.cis_id = iso_qos.ucast.cis;
+ if (!io_get_qos(io, &iso_qos)) {
+ g_io_channel_unref(io);
+ return;
}
- DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd,
- qos->ucast.cig_id, qos->ucast.cis_id);
- break;
- case BT_BAP_STREAM_TYPE_BCAST:
- /* Attempt to get BIG/BIS if they have not been set */
- if (setup->qos.bcast.big == BT_ISO_QOS_BIG_UNSET ||
- setup->qos.bcast.bis == BT_ISO_QOS_BIS_UNSET) {
- struct bt_iso_qos iso_qos;
+ qos->ucast.cig_id = iso_qos.ucast.cig;
+ qos->ucast.cis_id = iso_qos.ucast.cis;
+ }
- if (!io_get_qos(io, &iso_qos)) {
- g_io_channel_unref(io);
- return;
- }
+ DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd,
+ qos->ucast.cig_id, qos->ucast.cis_id);
+}
- qos->bcast.big = iso_qos.bcast.big;
- qos->bcast.bis = iso_qos.bcast.bis;
- bt_bap_stream_config(setup->stream, qos, setup->caps,
- NULL, NULL);
+static void bap_connecting_bcast(struct bt_bap_stream *stream, bool state,
+ int fd, void *user_data)
+{
+ struct bap_data *data = user_data;
+ struct bap_setup *setup;
+ GIOChannel *io;
+
+ if (!state)
+ return;
+
+ setup = bap_find_setup_by_stream(data, stream);
+ if (!setup)
+ return;
+
+ setup->recreate = false;
+
+ if (!setup->io) {
+ io = g_io_channel_unix_new(fd);
+ setup->io_id = g_io_add_watch(io,
+ G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ setup_io_disconnected, setup);
+ setup->io = io;
+ } else
+ io = setup->io;
+
+ g_io_channel_set_close_on_unref(io, FALSE);
+
+ /* Attempt to get BIG/BIS if they have not been set */
+ if (setup->qos.bcast.big == BT_ISO_QOS_BIG_UNSET ||
+ setup->qos.bcast.bis == BT_ISO_QOS_BIS_UNSET) {
+ struct bt_iso_qos iso_qos;
+
+ if (!io_get_qos(io, &iso_qos)) {
+ g_io_channel_unref(io);
+ return;
}
- DBG("stream %p fd %d: BIG 0x%02x BIS 0x%02x", stream, fd,
- qos->bcast.big, qos->bcast.bis);
+ setup->qos.bcast.big = iso_qos.bcast.big;
+ setup->qos.bcast.bis = iso_qos.bcast.bis;
+ bt_bap_stream_config(setup->stream, &setup->qos, setup->caps,
+ NULL, NULL);
}
+
+ DBG("stream %p fd %d: BIG 0x%02x BIS 0x%02x", stream, fd,
+ setup->qos.bcast.big, setup->qos.bcast.bis);
}
static void bap_attached(struct bt_bap *bap, void *user_data)
@@ -2468,10 +2525,10 @@ static int bap_bcast_probe(struct btd_service *service)
data->ready_id = bt_bap_ready_register(data->bap, bap_ready, service,
NULL);
- data->state_id = bt_bap_state_register(data->bap, bap_state,
- bap_connecting, data, NULL);
+ data->state_id = bt_bap_state_register(data->bap, bap_state_bcast,
+ bap_connecting_bcast, data, NULL);
data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast,
- pac_removed_broadcast, data, NULL);
+ pac_removed_broadcast, data, NULL);
bt_bap_set_user_data(data->bap, service);
@@ -2623,8 +2680,8 @@ static int bap_adapter_probe(struct btd_profile *p,
return -EINVAL;
}
- data->state_id = bt_bap_state_register(data->bap, bap_state,
- bap_connecting, data, NULL);
+ data->state_id = bt_bap_state_register(data->bap, bap_state_bcast,
+ bap_connecting_bcast, data, NULL);
data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast,
pac_removed_broadcast, data, NULL);