Bluetooth: ISO: Add ISO limits as #defines and use them

Add #define's for ISO HCI limits and use them to validate
input parameters.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2021-08-24 16:46:46 +02:00 committed by Anas Nashif
commit d8d8d82f0e
2 changed files with 241 additions and 28 deletions

View file

@ -37,6 +37,43 @@ extern "C" {
/** Value to set the ISO data path over HCi. */
#define BT_ISO_DATA_PATH_HCI 0x00
/** Minimum interval value in microseconds */
#define BT_ISO_INTERVAL_MIN 0x0000FF
/** Maximum interval value in microseconds */
#define BT_ISO_INTERVAL_MAX 0x0FFFFF
/** Minimum latency value in milliseconds */
#define BT_ISO_LATENCY_MIN 0x0005
/** Maximum latency value in milliseconds */
#define BT_ISO_LATENCY_MAX 0x0FA0
/** Packets will be sent sequentially between the channels in the group */
#define BT_ISO_PACKING_SEQUENTIAL 0x00
/** Packets will be sent interleaved between the channels in the group */
#define BT_ISO_PACKING_INTERLEAVED 0x01
/** Packets may be framed or unframed */
#define BT_ISO_FRAMING_UNFRAMED 0x00
/** Packets are always framed */
#define BT_ISO_FRAMING_FRAMED 0x01
/** Maximum number of isochronous channels in a single group */
#define BT_ISO_MAX_GROUP_ISO_COUNT 0x1F
/** Maximum SDU size */
#define BT_ISO_MAX_SDU 0x0FFF
/** Minimum BIG sync timeout value (N * 10 ms) */
#define BT_ISO_SYNC_TIMEOUT_MIN 0x000A
/** Maximum BIG sync timeout value (N * 10 ms) */
#define BT_ISO_SYNC_TIMEOUT_MAX 0x4000
/** Controller controlled maximum subevent count value */
#define BT_ISO_SYNC_MSE_ANY 0x00
/** Minimum BIG sync maximum subevent count value */
#define BT_ISO_SYNC_MSE_MIN 0x01
/** Maximum BIG sync maximum subevent count value */
#define BT_ISO_SYNC_MSE_MAX 0x1F
/** Maximum connected ISO retransmission value */
#define BT_ISO_CONNECTED_RTN_MAX 0xFF
/** Maximum broadcast ISO retransmission value */
#define BT_ISO_BROADCAST_RTN_MAX 0x1E
/** Broadcast code size */
#define BT_ISO_BROADCAST_CODE_SIZE 16
struct bt_iso_chan;
/** @brief Life-span states of ISO channel. Used only by internal APIs
@ -70,13 +107,13 @@ struct bt_iso_chan {
/** @brief ISO Channel IO QoS structure. */
struct bt_iso_chan_io_qos {
/** Channel SDU. Value range 0x0000 - 0x0FFF. */
/** Channel SDU. Maximum value is BT_ISO_MAX_SDU */
uint16_t sdu;
/** Channel PHY - See BT_GAP_LE_PHY for values.
* Setting BT_GAP_LE_PHY_NONE is invalid.
*/
uint8_t phy;
/** Channel Retransmission Number. Value range 0x00 - 0x0F. */
/** Channel Retransmission Number. */
uint8_t rtn;
/** @brief Channel data path reference
*
@ -156,19 +193,29 @@ struct bt_iso_recv_info {
struct bt_iso_cig;
struct bt_iso_cig_create_param {
/** Array of pointers to CIS channels
/** @brief Array of pointers to CIS channels
*
* This array shall remain valid for the duration of the CIG.
*/
struct bt_iso_chan **cis_channels;
/** Number channels in @p cis_channels */
/** @brief Number channels in @p cis_channels
*
* Maximum number of channels in a single group is
* BT_ISO_MAX_GROUP_ISO_COUNT
*/
uint8_t num_cis;
/** Channel interval in us. Value range 0x0000FF - 0xFFFFFF. */
/** @brief Channel interval in us.
*
* Value range BT_ISO_INTERVAL_MIN - BT_ISO_INTERVAL_MAX.
*/
uint32_t interval;
/** Channel Latency in ms. Value range 0x0005 - 0x0FA0. */
/** @brief Channel Latency in ms.
*
* Value range BT_ISO_LATENCY_MIN - BT_ISO_LATENCY_MAX.
*/
uint16_t latency;
/** @brief Channel peripherals sleep clock accuracy Only for CIS
@ -180,10 +227,17 @@ struct bt_iso_cig_create_param {
*/
uint8_t sca;
/** Channel packing mode. 0 for unpacked, 1 for packed. */
/** @brief Channel packing mode.
*
* BT_ISO_PACKING_SEQUENTIAL or BT_ISO_PACKING_INTERLEAVED
*/
uint8_t packing;
/** Channel framing mode. 0 for unframed, 1 for framed. */
/** @brief Channel framing mode.
*
* BT_ISO_FRAMING_UNFRAMED for unframed and
* BT_ISO_FRAMING_FRAMED for framed.
*/
uint8_t framing;
};
@ -205,19 +259,36 @@ struct bt_iso_big_create_param {
*/
struct bt_iso_chan **bis_channels;
/** Number channels in @p bis_channels */
/** @brief Number channels in @p bis_channels
*
* Maximum number of channels in a single group is
* BT_ISO_MAX_GROUP_ISO_COUNT
*/
uint8_t num_bis;
/** Channel interval in us. Value range 0x0000FF - 0xFFFFFF. */
/** @brief Channel interval in us.
*
* Value range BT_ISO_INTERVAL_MIN - BT_ISO_INTERVAL_MAX.
*/
uint32_t interval;
/** Channel Latency in ms. Value range 0x0005 - 0x0FA0. */
/** @brief Channel Latency in ms.
*
* Value range BT_ISO_LATENCY_MIN - BT_ISO_LATENCY_MAX.
*/
uint16_t latency;
/** Channel packing mode. 0 for unpacked, 1 for packed. */
/** @brief Channel packing mode.
*
* BT_ISO_PACKING_SEQUENTIAL or BT_ISO_PACKING_INTERLEAVED
*/
uint8_t packing;
/** Channel framing mode. 0 for unframed, 1 for framed. */
/** @brief Channel framing mode.
*
* BT_ISO_FRAMING_UNFRAMED for unframed and
* BT_ISO_FRAMING_FRAMED for framed.
*/
uint8_t framing;
/** Whether or not to encrypt the streams. */
@ -228,14 +299,18 @@ struct bt_iso_big_create_param {
* The code used to derive the session key that is used to encrypt and
* decrypt BIS payloads.
*/
uint8_t bcode[16];
uint8_t bcode[BT_ISO_BROADCAST_CODE_SIZE];
};
struct bt_iso_big_sync_param {
/** Array of pointers to BIS channels */
struct bt_iso_chan **bis_channels;
/** Number channels in @p bis_channels */
/** @brief Number channels in @p bis_channels
*
* Maximum number of channels in a single group is
* BT_ISO_MAX_GROUP_ISO_COUNT
*/
uint8_t num_bis;
/** Bitfield of the BISes to sync to */
@ -243,12 +318,19 @@ struct bt_iso_big_sync_param {
/** @brief Maximum subevents
*
* The MSE (Maximum Subevents) parameter is the maximum number of subevents that a
* Controller should use to receive data payloads in each interval for a BIS
* The MSE (Maximum Subevents) parameter is the maximum number of
* subevents that a Controller should use to receive data payloads
* in each interval for a BIS.
*
* Value range is BT_ISO_SYNC_MSE_MIN to BT_ISO_SYNC_MSE_MAX, or
* BT_ISO_SYNC_MSE_ANY to let the controller choose.
*/
uint32_t mse;
/** Synchronization timeout for the BIG (N * 10 MS) */
/** @brief Synchronization timeout for the BIG (N * 10 MS)
*
* Value range is BT_ISO_SYNC_TIMEOUT_MIN to BT_ISO_SYNC_TIMEOUT_MAX.
*/
uint16_t sync_timeout;
/** Whether or not the streams of the BIG are encrypted */
@ -259,7 +341,7 @@ struct bt_iso_big_sync_param {
* The code used to derive the session key that is used to encrypt and
* decrypt BIS payloads.
*/
uint8_t bcode[16];
uint8_t bcode[BT_ISO_BROADCAST_CODE_SIZE];
};
struct bt_iso_biginfo {

View file

@ -664,7 +664,50 @@ struct bt_conn_iso *bt_conn_iso(struct bt_conn *conn)
return &conn->iso;
}
static bool valid_chan_io_qos(const struct bt_iso_chan_io_qos *io_qos,
bool is_tx)
{
const size_t max_mtu = (is_tx ? CONFIG_BT_ISO_TX_MTU : CONFIG_BT_ISO_RX_MTU) -
BT_ISO_CHAN_SEND_RESERVE;
const size_t max_sdu = MIN(max_mtu, BT_ISO_MAX_SDU);
if (io_qos->sdu > max_sdu) {
BT_DBG("sdu (%u) shall be smaller than %u",
io_qos->sdu, max_sdu);
return false;
}
if (io_qos->phy > BT_GAP_LE_PHY_CODED) {
BT_DBG("Invalid phy %u", io_qos->phy);
return false;
}
return true;
}
#if defined(CONFIG_BT_ISO_UNICAST)
static bool valid_chan_qos(const struct bt_iso_chan_qos *qos)
{
if (qos->rx != NULL) {
if (!valid_chan_io_qos(qos->rx, false)) {
BT_DBG("Invalid rx qos");
return false;
}
} else if (qos->tx == NULL) {
BT_DBG("Both rx and tx qos are NULL");
return false;
}
if (qos->tx != NULL) {
if (!valid_chan_io_qos(qos->tx, true)) {
BT_DBG("Invalid tx qos");
return false;
}
}
return true;
}
void bt_iso_cleanup(struct bt_conn *conn)
{
struct bt_conn_iso *iso = bt_conn_iso(conn);
@ -953,11 +996,16 @@ static int cig_init_cis(struct bt_iso_cig *cig)
for (int i = 0; i < cig->num_cis; i++) {
struct bt_iso_chan *cis = cig->cis[i];
if (cis == NULL) {
CHECKIF(cis == NULL) {
BT_DBG("CIS was NULL");
return -EINVAL;
}
CHECKIF(valid_chan_qos(cis->qos)) {
BT_DBG("Invalid QOS");
return -EINVAL;
}
if (cis->conn) {
BT_DBG("CIS conn was already allocated");
return -EALREADY;
@ -1023,6 +1071,44 @@ int bt_iso_cig_create(const struct bt_iso_cig_create_param *param,
return -EINVAL;
}
for (int i = 0; i < param->num_cis; i++) {
CHECKIF(param->cis_channels[i] == NULL) {
BT_DBG("NULL channel in cis_channels[%d]", i);
return -EINVAL;
}
}
CHECKIF(param->framing != BT_ISO_FRAMING_UNFRAMED &&
param->framing != BT_ISO_FRAMING_FRAMED) {
BT_DBG("Invalid framing parameter: %u", param->framing);
return -EINVAL;
}
CHECKIF(param->packing != BT_ISO_PACKING_SEQUENTIAL &&
param->packing != BT_ISO_PACKING_INTERLEAVED) {
BT_DBG("Invalid framing parameter: %u", param->framing);
return -EINVAL;
}
CHECKIF(param->num_cis > BT_ISO_MAX_GROUP_ISO_COUNT ||
param->num_cis > CONFIG_BT_ISO_MAX_CHAN) {
BT_DBG("num_cis (%u) shall be lower than: %u", param->num_cis,
MAX(CONFIG_BT_ISO_MAX_CHAN, BT_ISO_MAX_GROUP_ISO_COUNT));
return -EINVAL;
}
CHECKIF(param->interval < BT_ISO_INTERVAL_MIN ||
param->interval > BT_ISO_INTERVAL_MAX) {
BT_DBG("Invalid interval: %u", param->interval);
return -EINVAL;
}
CHECKIF(param->latency < BT_ISO_LATENCY_MIN ||
param->latency > BT_ISO_LATENCY_MAX) {
BT_DBG("Invalid latency: %u", param->latency);
return -EINVAL;
}
cig = get_free_cig();
if (!cig) {
@ -1352,11 +1438,24 @@ static int big_init_bis(struct bt_iso_big *big, bool broadcaster)
return -EALREADY;
}
if (!bis->qos || (!bis->qos->tx && broadcaster)) {
BT_DBG("BIS QOS was invalid");
CHECKIF(bis->qos == NULL) {
BT_DBG("BIS QOS is NULL");
return -EINVAL;
}
if (broadcaster) {
CHECKIF(bis->qos->tx == NULL ||
valid_chan_io_qos(bis->qos->tx, true)) {
BT_DBG("Invalid BIS QOS");
return -EINVAL;
}
} else {
CHECKIF(bis->qos->rx == NULL) {
BT_DBG("Invalid BIS QOS");
return -EINVAL;
}
}
bis->conn = iso_new();
if (!bis->conn) {
@ -1446,12 +1545,43 @@ int bt_iso_big_create(struct bt_le_ext_adv *padv, struct bt_iso_big_create_param
}
for (int i = 0; i < param->num_bis; i++) {
if (param->bis_channels[i] == NULL) {
CHECKIF(param->bis_channels[i] == NULL) {
BT_DBG("NULL channel in bis_channels[%d]", i);
return -EINVAL;
}
}
CHECKIF(param->framing != BT_ISO_FRAMING_UNFRAMED &&
param->framing != BT_ISO_FRAMING_FRAMED) {
BT_DBG("Invalid framing parameter: %u", param->framing);
return -EINVAL;
}
CHECKIF(param->packing != BT_ISO_PACKING_SEQUENTIAL &&
param->packing != BT_ISO_PACKING_INTERLEAVED) {
BT_DBG("Invalid framing parameter: %u", param->framing);
return -EINVAL;
}
CHECKIF(param->num_bis > BT_ISO_MAX_GROUP_ISO_COUNT ||
param->num_bis > CONFIG_BT_ISO_MAX_CHAN) {
BT_DBG("num_bis (%u) shall be lower than: %u", param->num_bis,
MAX(CONFIG_BT_ISO_MAX_CHAN, BT_ISO_MAX_GROUP_ISO_COUNT));
return -EINVAL;
}
CHECKIF(param->interval < BT_ISO_INTERVAL_MIN ||
param->interval > BT_ISO_INTERVAL_MAX) {
BT_DBG("Invalid interval: %u", param->interval);
return -EINVAL;
}
CHECKIF(param->latency < BT_ISO_LATENCY_MIN ||
param->latency > BT_ISO_LATENCY_MAX) {
BT_DBG("Invalid latency: %u", param->latency);
return -EINVAL;
}
big = get_free_big();
if (!big) {
@ -1722,7 +1852,7 @@ static int hci_le_big_create_sync(const struct bt_le_per_adv_sync *sync, struct
req->sync_timeout = sys_cpu_to_le16(param->sync_timeout);
req->num_bis = big->num_bis;
/* Transform from bitfield to array */
for (int i = 0; i < 0x1F; i++) {
for (int i = 0; i < BT_ISO_MAX_GROUP_ISO_COUNT; i++) {
if (param->bis_bitfield & BIT(i)) {
if (bit_idx == big->num_bis) {
BT_DBG("BIG cannot contain %u BISes", bit_idx + 1);
@ -1755,12 +1885,13 @@ int bt_iso_big_sync(struct bt_le_per_adv_sync *sync, struct bt_iso_big_sync_para
return -EINVAL;
}
CHECKIF(param->mse > 0x1F) {
CHECKIF(param->mse > BT_ISO_SYNC_MSE_MAX) {
BT_DBG("Invalid MSE 0x%02x", param->mse);
return -EINVAL;
}
CHECKIF(param->sync_timeout < 0x000A || param->sync_timeout > 0x4000) {
CHECKIF(param->sync_timeout < BT_ISO_SYNC_TIMEOUT_MIN ||
param->sync_timeout > BT_ISO_SYNC_TIMEOUT_MAX) {
BT_DBG("Invalid sync timeout 0x%04x", param->sync_timeout);
return -EINVAL;
}