From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> BT_HCI_CMD_LE_TERM_BIG shall cleanup the BIS connections and if there are remote connected then they shall be notified with BT_HCI_EVT_LE_BIG_SYNC_LOST so they can proceed to cleanup as well. --- emulator/btdev.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/emulator/btdev.c b/emulator/btdev.c index 7293e2f2e5f1..3747eaaef842 100644 --- a/emulator/btdev.c +++ b/emulator/btdev.c @@ -6538,7 +6538,33 @@ static int cmd_create_big_test(struct btdev *dev, const void *data, uint8_t len) static int cmd_term_big(struct btdev *dev, const void *data, uint8_t len) { - cmd_status(dev, BT_HCI_ERR_SUCCESS, BT_HCI_CMD_LE_TERM_BIG); + const struct bt_hci_cmd_le_term_big *cmd = data; + struct le_big *big; + uint8_t status = BT_HCI_ERR_SUCCESS; + + /* Check that PA advertising is enabled othewise it is not possible to + * have a BIG. + */ + if (!dev->le_pa_enable) { + status = BT_HCI_ERR_UNKNOWN_ADVERTISING_ID; + goto done; + } + + /* If the BIG_Handle does not identify a BIG, the Controller shall + * return the error code Unknown Advertising Identifier (0x42). + */ + big = queue_find(dev->le_big, match_big_handle, + UINT_TO_PTR(cmd->handle)); + if (!big) { + status = BT_HCI_ERR_UNKNOWN_ADVERTISING_ID; + goto done; + } + +done: + cmd_status(dev, status, BT_HCI_CMD_LE_TERM_BIG); + + if (status) + return -EALREADY; return 0; } @@ -6548,6 +6574,9 @@ static int cmd_term_big_complete(struct btdev *dev, const void *data, { const struct bt_hci_cmd_le_term_big *cmd = data; struct bt_hci_evt_le_big_terminate rsp; + struct le_big *big; + struct btdev_conn *conn; + struct btdev *remote = NULL; memset(&rsp, 0, sizeof(rsp)); rsp.reason = cmd->reason; @@ -6555,6 +6584,40 @@ static int cmd_term_big_complete(struct btdev *dev, const void *data, le_meta_event(dev, BT_HCI_EVT_LE_BIG_TERMINATE, &rsp, sizeof(rsp)); + big = queue_find(dev->le_big, match_big_handle, + UINT_TO_PTR(cmd->handle)); + + if (!big) + return 0; + + /* Cleanup existing connections */ + while ((conn = queue_pop_head(big->bis))) { + if (!conn->link) { + conn_remove(conn); + continue; + } + + /* Send BIG Sync Lost event once per remote device */ + if (conn->link->dev != remote) { + struct bt_hci_evt_le_big_sync_lost evt; + + memset(&evt, 0, sizeof(evt)); + evt.big_handle = cmd->handle; + evt.reason = cmd->reason; + + remote = conn->link->dev; + le_meta_event(remote, BT_HCI_EVT_LE_BIG_SYNC_LOST, + &evt, sizeof(evt)); + } + + /* Unlink conn from remote BIS */ + conn_unlink(conn, conn->link); + conn_remove(conn); + } + + queue_remove(dev->le_big, big); + le_big_free(big); + return 0; } @@ -7587,6 +7650,8 @@ static const struct btdev_cmd *run_cmd(struct btdev *btdev, case -ENOENT: status = BT_HCI_ERR_UNKNOWN_CONN_ID; break; + case -EALREADY: + return NULL; default: status = BT_HCI_ERR_UNSPECIFIED_ERROR; break; -- 2.50.1