zephyr/subsys/bluetooth/audio/ascs_internal.h
Fredrik Danebjer c9da274eb2 Bluetooth: ascs: Add dynamic ASE registration
Added option to set the ASE count through the bap API, making ASE
configuration runtime available. The upper limit of ASEs are still
bound by the Kconfig options set for ASEs.

Signed-off-by: Fredrik Danebjer <frdn@demant.com>
2024-09-11 07:41:12 -04:00

365 lines
8.4 KiB
C

/* @file
* @brief Internal APIs for ASCS handling
* Copyright (c) 2020 Intel Corporation
* Copyright (c) 2022-2023 Nordic Semiconductor ASA
* Copyright (c) 2024 Demant A/S
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef BT_ASCS_INTERNAL_H
#define BT_ASCS_INTERNAL_H
#include <zephyr/bluetooth/audio/audio.h>
#include <zephyr/bluetooth/audio/bap.h>
#include <zephyr/bluetooth/conn.h>
#define BT_ASCS_ASE_ID_NONE 0x00
/* The number of ASEs in the notification when the opcode is unsupported or the length of the
* control point write request is incorrect
*/
#define BT_ASCS_UNSUPP_OR_LENGTH_ERR_NUM_ASE 0xFFU
/* Transport QoS Packing */
#define BT_ASCS_QOS_PACKING_SEQ 0x00
#define BT_ASCS_QOS_PACKING_INT 0x01
/* Transport QoS Framing */
#define BT_ASCS_QOS_FRAMING_UNFRAMED 0x00
#define BT_ASCS_QOS_FRAMING_FRAMED 0x01
/* Format of the ASE characteristic, defined in Table 4.2 */
struct bt_ascs_ase_status {
uint8_t id;
uint8_t state;
uint8_t params[0];
} __packed;
struct bt_ascs_codec_config {
uint8_t len;
uint8_t type;
uint8_t data[0];
} __packed;
struct bt_ascs_codec {
uint8_t id;
uint16_t cid;
uint16_t vid;
} __packed;
#define BT_ASCS_PD_NO_PREF 0x00000000
/* ASE_State = 0x01 (Codec Configured), defined in Table 4.3. */
struct bt_ascs_ase_status_config {
uint8_t framing;
uint8_t phy;
uint8_t rtn;
uint16_t latency;
uint8_t pd_min[3];
uint8_t pd_max[3];
uint8_t prefer_pd_min[3];
uint8_t prefer_pd_max[3];
struct bt_ascs_codec codec;
uint8_t cc_len;
/* LTV-formatted Codec-Specific Configuration */
struct bt_ascs_codec_config cc[0];
} __packed;
/* ASE_State = 0x02 (QoS Configured), defined in Table 4.4. */
struct bt_ascs_ase_status_qos {
uint8_t cig_id;
uint8_t cis_id;
uint8_t interval[3];
uint8_t framing;
uint8_t phy;
uint16_t sdu;
uint8_t rtn;
uint16_t latency;
uint8_t pd[3];
} __packed;
/* ASE_Status = 0x03 (Enabling) defined in Table 4.5.
*/
struct bt_ascs_ase_status_enable {
uint8_t cig_id;
uint8_t cis_id;
uint8_t metadata_len;
uint8_t metadata[0];
} __packed;
/* ASE_Status = 0x04 (Streaming) defined in Table 4.5.
*/
struct bt_ascs_ase_status_stream {
uint8_t cig_id;
uint8_t cis_id;
uint8_t metadata_len;
uint8_t metadata[0];
} __packed;
/* ASE_Status = 0x05 (Disabling) as defined in Table 4.5.
*/
struct bt_ascs_ase_status_disable {
uint8_t cig_id;
uint8_t cis_id;
uint8_t metadata_len;
uint8_t metadata[0];
} __packed;
/* ASE Control Point Protocol */
struct bt_ascs_ase_cp {
/* Request/Notification opcode */
uint8_t op;
uint8_t pdu[0];
} __packed;
/* Opcodes */
#define BT_ASCS_CONFIG_OP 0x01
#define BT_ASCS_CONFIG_LATENCY_LOW 0x01
#define BT_ASCS_CONFIG_LATENCY_MEDIUM 0x02
#define BT_ASCS_CONFIG_LATENCY_HIGH 0x03
#define BT_ASCS_CONFIG_PHY_LE_1M 0x01
#define BT_ASCS_CONFIG_PHY_LE_2M 0x02
#define BT_ASCS_CONFIG_PHY_LE_CODED 0x03
struct bt_ascs_config {
/* ASE ID */
uint8_t ase;
/* Target latency */
uint8_t latency;
/* Target PHY */
uint8_t phy;
/* Codec ID */
struct bt_ascs_codec codec;
/* Codec Specific Config Length */
uint8_t cc_len;
/* LTV-formatted Codec-Specific Configuration */
struct bt_ascs_codec_config cc[0];
} __packed;
struct bt_ascs_config_op {
/* Number of ASEs */
uint8_t num_ases;
/* Config Parameters */
struct bt_ascs_config cfg[0];
} __packed;
#define BT_ASCS_QOS_OP 0x02
struct bt_ascs_qos {
/* ASE ID */
uint8_t ase;
/* CIG ID*/
uint8_t cig;
/* CIG ID*/
uint8_t cis;
/* Frame interval */
uint8_t interval[3];
/* Frame framing */
uint8_t framing;
/* PHY */
uint8_t phy;
/* Maximum SDU Size */
uint16_t sdu;
/* Retransmission Effort */
uint8_t rtn;
/* Transport Latency */
uint16_t latency;
/* Presentation Delay */
uint8_t pd[3];
} __packed;
struct bt_ascs_qos_op {
/* Number of ASEs */
uint8_t num_ases;
/* QoS Parameters */
struct bt_ascs_qos qos[0];
} __packed;
#define BT_ASCS_ENABLE_OP 0x03
struct bt_ascs_metadata {
/* ASE ID */
uint8_t ase;
/* Metadata length */
uint8_t len;
/* LTV-formatted Metadata */
uint8_t data[0];
} __packed;
struct bt_ascs_enable_op {
/* Number of ASEs */
uint8_t num_ases;
/* Metadata */
struct bt_ascs_metadata metadata[0];
} __packed;
#define BT_ASCS_START_OP 0x04
struct bt_ascs_start_op {
/* Number of ASEs */
uint8_t num_ases;
/* ASE IDs */
uint8_t ase[0];
} __packed;
#define BT_ASCS_DISABLE_OP 0x05
struct bt_ascs_disable_op {
/* Number of ASEs */
uint8_t num_ases;
/* ASE IDs */
uint8_t ase[0];
} __packed;
#define BT_ASCS_STOP_OP 0x06
struct bt_ascs_stop_op {
/* Number of ASEs */
uint8_t num_ases;
/* ASE IDs */
uint8_t ase[0];
} __packed;
#define BT_ASCS_METADATA_OP 0x07
struct bt_ascs_metadata_op {
/* Number of ASEs */
uint8_t num_ases;
/* Metadata */
struct bt_ascs_metadata metadata[0];
} __packed;
#define BT_ASCS_RELEASE_OP 0x08
struct bt_ascs_release_op {
/* Number of ASEs */
uint8_t num_ases;
/* Ase IDs */
uint8_t ase[0];
} __packed;
struct bt_ascs_cp_ase_rsp {
/* ASE ID */
uint8_t id;
/* Response code */
uint8_t code;
/* Response reason */
uint8_t reason;
} __packed;
struct bt_ascs_cp_rsp {
/* Opcode */
uint8_t op;
/* Number of ASEs */
uint8_t num_ase;
/* ASE response */
struct bt_ascs_cp_ase_rsp ase_rsp[0];
} __packed;
static inline const char *bt_ascs_op_str(uint8_t op)
{
switch (op) {
case BT_ASCS_CONFIG_OP:
return "Config Codec";
case BT_ASCS_QOS_OP:
return "Config QoS";
case BT_ASCS_ENABLE_OP:
return "Enable";
case BT_ASCS_START_OP:
return "Receiver Start Ready";
case BT_ASCS_DISABLE_OP:
return "Disable";
case BT_ASCS_STOP_OP:
return "Receiver Stop Ready";
case BT_ASCS_METADATA_OP:
return "Update Metadata";
case BT_ASCS_RELEASE_OP:
return "Release";
}
return "Unknown";
}
static inline const char *bt_ascs_rsp_str(uint8_t code)
{
switch (code) {
case BT_BAP_ASCS_RSP_CODE_SUCCESS:
return "Success";
case BT_BAP_ASCS_RSP_CODE_NOT_SUPPORTED:
return "Unsupported Opcode";
case BT_BAP_ASCS_RSP_CODE_INVALID_LENGTH:
return "Invalid Length";
case BT_BAP_ASCS_RSP_CODE_INVALID_ASE:
return "Invalid ASE_ID";
case BT_BAP_ASCS_RSP_CODE_INVALID_ASE_STATE:
return "Invalid ASE State";
case BT_BAP_ASCS_RSP_CODE_INVALID_DIR:
return "Invalid ASE Direction";
case BT_BAP_ASCS_RSP_CODE_CAP_UNSUPPORTED:
return "Unsupported Capabilities";
case BT_BAP_ASCS_RSP_CODE_CONF_UNSUPPORTED:
return "Unsupported Configuration Value";
case BT_BAP_ASCS_RSP_CODE_CONF_REJECTED:
return "Rejected Configuration Value";
case BT_BAP_ASCS_RSP_CODE_CONF_INVALID:
return "Invalid Configuration Value";
case BT_BAP_ASCS_RSP_CODE_METADATA_UNSUPPORTED:
return "Unsupported Metadata";
case BT_BAP_ASCS_RSP_CODE_METADATA_REJECTED:
return "Rejected Metadata";
case BT_BAP_ASCS_RSP_CODE_METADATA_INVALID:
return "Invalid Metadata";
case BT_BAP_ASCS_RSP_CODE_NO_MEM:
return "Insufficient Resources";
case BT_BAP_ASCS_RSP_CODE_UNSPECIFIED:
return "Unspecified Error";
}
return "Unknown";
}
static inline const char *bt_ascs_reason_str(uint8_t reason)
{
switch (reason) {
case BT_BAP_ASCS_REASON_NONE:
return "None";
case BT_BAP_ASCS_REASON_CODEC:
return "Codec ID";
case BT_BAP_ASCS_REASON_CODEC_DATA:
return "Codec Specific Configuration";
case BT_BAP_ASCS_REASON_INTERVAL:
return "SDU Interval";
case BT_BAP_ASCS_REASON_FRAMING:
return "Framing";
case BT_BAP_ASCS_REASON_PHY:
return "PHY";
case BT_BAP_ASCS_REASON_SDU:
return "Maximum SDU Size";
case BT_BAP_ASCS_REASON_RTN:
return "Retransmission Number";
case BT_BAP_ASCS_REASON_LATENCY:
return "Maximum Transport Delay";
case BT_BAP_ASCS_REASON_PD:
return "Presentation Delay";
case BT_BAP_ASCS_REASON_CIS:
return "Invalid ASE CIS Mapping";
}
return "Unknown";
}
int bt_ascs_init(const struct bt_bap_unicast_server_cb *cb);
void bt_ascs_cleanup(void);
int ascs_ep_set_state(struct bt_bap_ep *ep, uint8_t state);
int bt_ascs_config_ase(struct bt_conn *conn, struct bt_bap_stream *stream,
struct bt_audio_codec_cfg *codec_cfg,
const struct bt_audio_codec_qos_pref *qos_pref);
int bt_ascs_disable_ase(struct bt_bap_ep *ep);
int bt_ascs_release_ase(struct bt_bap_ep *ep);
void bt_ascs_foreach_ep(struct bt_conn *conn, bt_bap_ep_func_t func, void *user_data);
int bt_ascs_register(uint8_t snk_cnt, uint8_t src_cnt);
int bt_ascs_unregister(void);
#endif /* BT_ASCS_INTERNAL_H */