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:
parent
50280c67cf
commit
d8d8d82f0e
2 changed files with 241 additions and 28 deletions
|
@ -35,7 +35,44 @@ extern "C" {
|
|||
BT_HCI_ISO_DATA_HDR_SIZE)
|
||||
|
||||
/** Value to set the ISO data path over HCi. */
|
||||
#define BT_ISO_DATA_PATH_HCI 0x00
|
||||
#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;
|
||||
|
||||
|
@ -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,37 +259,58 @@ 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. */
|
||||
bool encryption;
|
||||
bool encryption;
|
||||
|
||||
/** @brief Broadcast code
|
||||
*
|
||||
* 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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue