bluetooth: tester: MICP Client tests
Add support for MICP Client tests. Signed-off-by: Piotr Narajowski <piotr.narajowski@codecoup.pl>
This commit is contained in:
parent
96954acfff
commit
925a8b65d5
10 changed files with 1052 additions and 279 deletions
|
@ -43,3 +43,11 @@ endif()
|
||||||
if (CONFIG_BT_CSIP_SET_MEMBER)
|
if (CONFIG_BT_CSIP_SET_MEMBER)
|
||||||
target_sources(app PRIVATE src/btp_csis.c)
|
target_sources(app PRIVATE src/btp_csis.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_BT_MICP_MIC_DEV)
|
||||||
|
target_sources(app PRIVATE src/btp_micp.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_BT_AICS)
|
||||||
|
target_sources(app PRIVATE src/btp_aics.c)
|
||||||
|
endif()
|
||||||
|
|
|
@ -19,6 +19,12 @@ CONFIG_BT_BUF_CMD_TX_SIZE=255
|
||||||
# were freed too slow. The bt_bap_stream_ops.configured callback comes earlier.
|
# were freed too slow. The bt_bap_stream_ops.configured callback comes earlier.
|
||||||
CONFIG_BT_L2CAP_TX_BUF_COUNT=4
|
CONFIG_BT_L2CAP_TX_BUF_COUNT=4
|
||||||
|
|
||||||
|
# MICP
|
||||||
|
CONFIG_BT_MICP_MIC_DEV=y
|
||||||
|
CONFIG_BT_MICP_MIC_DEV_AICS_INSTANCE_COUNT=1
|
||||||
|
CONFIG_BT_MICP_MIC_CTLR=y
|
||||||
|
CONFIG_BT_MICP_MIC_CTLR_MAX_AICS_INST=1
|
||||||
|
|
||||||
# ASCS
|
# ASCS
|
||||||
CONFIG_BT_ASCS_ASE_SNK_COUNT=2
|
CONFIG_BT_ASCS_ASE_SNK_COUNT=2
|
||||||
CONFIG_BT_ASCS_ASE_SRC_COUNT=2
|
CONFIG_BT_ASCS_ASE_SRC_COUNT=2
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "btp_bap.h"
|
#include "btp_bap.h"
|
||||||
#include "btp_has.h"
|
#include "btp_has.h"
|
||||||
#include "btp_csis.h"
|
#include "btp_csis.h"
|
||||||
|
#include "btp_micp.h"
|
||||||
|
|
||||||
#define BTP_MTU 1024
|
#define BTP_MTU 1024
|
||||||
#define BTP_DATA_MAX_SIZE (BTP_MTU - sizeof(struct btp_hdr))
|
#define BTP_DATA_MAX_SIZE (BTP_MTU - sizeof(struct btp_hdr))
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
#define BTP_SERVICE_ID_ASCS 13
|
#define BTP_SERVICE_ID_ASCS 13
|
||||||
#define BTP_SERVICE_ID_BAP 14
|
#define BTP_SERVICE_ID_BAP 14
|
||||||
#define BTP_SERVICE_ID_HAS 15
|
#define BTP_SERVICE_ID_HAS 15
|
||||||
|
#define BTP_SERVICE_ID_MICP 16
|
||||||
#define BTP_SERVICE_ID_CSIS 17
|
#define BTP_SERVICE_ID_CSIS 17
|
||||||
|
|
||||||
#define BTP_SERVICE_ID_MAX BTP_SERVICE_ID_CSIS
|
#define BTP_SERVICE_ID_MAX BTP_SERVICE_ID_CSIS
|
||||||
|
|
|
@ -7,29 +7,125 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <zephyr/sys/util.h>
|
#include <zephyr/sys/util.h>
|
||||||
|
#include <zephyr/bluetooth/conn.h>
|
||||||
|
|
||||||
/*AICS service */
|
/*AICS service */
|
||||||
|
struct btp_aics_instance {
|
||||||
|
/** Number of Audio Input Control Service instances */
|
||||||
|
uint8_t aics_cnt;
|
||||||
|
/** Array of pointers to Audio Input Control Service instances */
|
||||||
|
struct bt_aics **aics;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct bt_aics_cb aics_client_cb;
|
||||||
|
extern struct btp_aics_instance aics_client_instance;
|
||||||
|
extern struct btp_aics_instance aics_server_instance;
|
||||||
|
void btp_send_aics_state_changed_ev(struct bt_conn *conn);
|
||||||
|
void btp_send_aics_state_ev(struct bt_conn *conn, int8_t gain, uint8_t mute, uint8_t mode);
|
||||||
|
void btp_send_gain_setting_properties_ev(struct bt_conn *conn, uint8_t units, int8_t minimum,
|
||||||
|
int8_t maximum);
|
||||||
|
void btp_send_aics_input_type_event(struct bt_conn *conn, uint8_t input_type);
|
||||||
|
void btp_send_aics_status_ev(struct bt_conn *conn, bool active);
|
||||||
|
void btp_send_aics_description_ev(struct bt_conn *conn, uint8_t data_len, char *description);
|
||||||
|
|
||||||
#define BTP_AICS_READ_SUPPORTED_COMMANDS 0x01
|
#define BTP_AICS_READ_SUPPORTED_COMMANDS 0x01
|
||||||
struct btp_aics_read_supported_commands_rp {
|
struct btp_aics_read_supported_commands_rp {
|
||||||
uint8_t data[0];
|
uint8_t data[0];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
/* AICS client/server commands */
|
||||||
#define BTP_AICS_SET_GAIN 0x02
|
#define BTP_AICS_SET_GAIN 0x02
|
||||||
struct btp_aics_set_gain_cmd {
|
struct btp_aics_set_gain_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
int8_t gain;
|
int8_t gain;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define BTP_AICS_MUTE 0x03
|
#define BTP_AICS_MUTE 0x03
|
||||||
#define BTP_AICS_UNMUTE 0x04
|
struct btp_aics_mute_cmd {
|
||||||
#define BTP_AICS_MAN_GAIN 0x05
|
bt_addr_le_t address;
|
||||||
#define BTP_AICS_AUTO_GAIN 0x06
|
} __packed;
|
||||||
#define BTP_AICS_MAN_GAIN_ONLY 0x07
|
|
||||||
#define BTP_AICS_AUTO_GAIN_ONLY 0x08
|
|
||||||
|
|
||||||
#define BTP_AICS_DESCRIPTION 0x09
|
#define BTP_AICS_UNMUTE 0x04
|
||||||
|
struct btp_aics_unmute_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_AICS_MAN_GAIN_SET 0x05
|
||||||
|
struct btp_aics_manual_gain_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_AICS_AUTO_GAIN_SET 0x06
|
||||||
|
struct btp_aics_auto_gain_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_AICS_SET_MAN_GAIN_ONLY 0x07
|
||||||
|
#define BTP_AICS_SET_AUTO_GAIN_ONLY 0x08
|
||||||
|
#define BTP_AICS_AUDIO_DESCRIPTION_SET 0x09
|
||||||
struct btp_aics_audio_desc_cmd {
|
struct btp_aics_audio_desc_cmd {
|
||||||
uint8_t desc_len;
|
uint8_t desc_len;
|
||||||
uint8_t desc[0];
|
uint8_t desc[0];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define BTP_AICS_MUTE_DISABLE 0x0a
|
#define BTP_AICS_MUTE_DISABLE 0x0a
|
||||||
|
#define BTP_AICS_GAIN_SETTING_PROP_GET 0x0b
|
||||||
|
struct btp_aics_gain_setting_prop_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_AICS_TYPE_GET 0x0c
|
||||||
|
struct btp_aics_type_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_AICS_STATUS_GET 0x0d
|
||||||
|
struct btp_aics_status_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_AICS_STATE_GET 0x0e
|
||||||
|
struct btp_aics_state_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_AICS_DESCRIPTION_GET 0x0f
|
||||||
|
struct btp_aics_desc_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* AICS events */
|
||||||
|
#define BTP_AICS_STATE_EV 0x80
|
||||||
|
struct btp_aics_state_ev {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
int8_t gain;
|
||||||
|
uint8_t mute;
|
||||||
|
uint8_t mode;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_GAIN_SETTING_PROPERTIES_EV 0x81
|
||||||
|
struct btp_gain_setting_properties_ev {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
uint8_t units;
|
||||||
|
int8_t minimum;
|
||||||
|
int8_t maximum;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_AICS_INPUT_TYPE_EV 0x82
|
||||||
|
struct btp_aics_input_type_ev {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
uint8_t input_type;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_AICS_STATUS_EV 0x83
|
||||||
|
struct btp_aics_status_ev {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
bool active;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_AICS_DESCRIPTION_EV 0x84
|
||||||
|
struct btp_aics_description_ev {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
uint8_t data_len;
|
||||||
|
char data[0];
|
||||||
|
} __packed;
|
||||||
|
|
47
tests/bluetooth/tester/src/btp/btp_micp.h
Normal file
47
tests/bluetooth/tester/src/btp/btp_micp.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/* btp_micp.h - Bluetooth tester headers */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Codecoup
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* MICP commands */
|
||||||
|
#define BTP_MICP_READ_SUPPORTED_COMMANDS 0x01
|
||||||
|
struct btp_micp_read_supported_commands_rp {
|
||||||
|
uint8_t data[0];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_MICP_CTLR_DISCOVER 0x02
|
||||||
|
struct btp_micp_discover_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_MICP_CTLR_MUTE_READ 0x03
|
||||||
|
struct btp_micp_mute_read_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_MICP_CTLR_MUTE 0x04
|
||||||
|
struct btp_micp_mute_cmd {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* MICP events */
|
||||||
|
#define BTP_MICP_DISCOVERED_EV 0x80
|
||||||
|
struct btp_micp_discovered_ev {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
uint16_t mute_handle;
|
||||||
|
uint16_t state_handle;
|
||||||
|
uint16_t gain_handle;
|
||||||
|
uint16_t type_handle;
|
||||||
|
uint16_t status_handle;
|
||||||
|
uint16_t control_handle;
|
||||||
|
uint16_t desc_handle;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define BTP_MICP_MUTE_STATE_EV 0x81
|
||||||
|
struct btp_micp_mute_state_ev {
|
||||||
|
bt_addr_le_t address;
|
||||||
|
uint8_t mute;
|
||||||
|
} __packed;
|
|
@ -92,3 +92,6 @@ uint8_t tester_unregister_has(void);
|
||||||
|
|
||||||
uint8_t tester_init_csis(void);
|
uint8_t tester_init_csis(void);
|
||||||
uint8_t tester_unregister_csis(void);
|
uint8_t tester_unregister_csis(void);
|
||||||
|
|
||||||
|
uint8_t tester_init_micp(void);
|
||||||
|
uint8_t tester_unregister_micp(void);
|
||||||
|
|
566
tests/bluetooth/tester/src/btp_aics.c
Normal file
566
tests/bluetooth/tester/src/btp_aics.c
Normal file
|
@ -0,0 +1,566 @@
|
||||||
|
/* btp_aics.c - Bluetooth AICS Tester */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Codecoup
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
|
#include <zephyr/bluetooth/bluetooth.h>
|
||||||
|
#include <zephyr/bluetooth/audio/audio.h>
|
||||||
|
#include <zephyr/bluetooth/audio/micp.h>
|
||||||
|
#include <zephyr/bluetooth/audio/aics.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/sys/byteorder.h>
|
||||||
|
|
||||||
|
#include "bap_endpoint.h"
|
||||||
|
#include "btp/btp.h"
|
||||||
|
|
||||||
|
#define LOG_MODULE_NAME bttester_aics
|
||||||
|
LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
|
||||||
|
|
||||||
|
#define BT_AICS_MAX_INPUT_DESCRIPTION_SIZE 16
|
||||||
|
#define BT_AICS_MAX_OUTPUT_DESCRIPTION_SIZE 16
|
||||||
|
|
||||||
|
struct btp_aics_instance aics_client_instance;
|
||||||
|
struct btp_aics_instance aics_server_instance;
|
||||||
|
|
||||||
|
static struct net_buf_simple *rx_ev_buf = NET_BUF_SIMPLE(BT_AICS_MAX_INPUT_DESCRIPTION_SIZE +
|
||||||
|
sizeof(struct btp_aics_description_ev));
|
||||||
|
|
||||||
|
static uint8_t aics_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp,
|
||||||
|
uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
struct btp_aics_read_supported_commands_rp *rp = rsp;
|
||||||
|
|
||||||
|
/* octet 0 */
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_READ_SUPPORTED_COMMANDS);
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_SET_GAIN);
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_MUTE);
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_UNMUTE);
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_MAN_GAIN_SET);
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_AUTO_GAIN_SET);
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_SET_MAN_GAIN_ONLY);
|
||||||
|
|
||||||
|
/* octet 1 */
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_SET_AUTO_GAIN_ONLY);
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_AUDIO_DESCRIPTION_SET);
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_MUTE_DISABLE);
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_GAIN_SETTING_PROP_GET);
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_TYPE_GET);
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_STATUS_GET);
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_STATE_GET);
|
||||||
|
|
||||||
|
/* octet 2 */
|
||||||
|
tester_set_bit(rp->data, BTP_AICS_DESCRIPTION_GET);
|
||||||
|
|
||||||
|
*rsp_len = sizeof(*rp) + 2;
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btp_send_aics_state_ev(struct bt_conn *conn, int8_t gain, uint8_t mute, uint8_t mode)
|
||||||
|
{
|
||||||
|
struct btp_aics_state_ev ev;
|
||||||
|
|
||||||
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
|
|
||||||
|
ev.gain = gain;
|
||||||
|
ev.mute = mute;
|
||||||
|
ev.mode = mode;
|
||||||
|
|
||||||
|
tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_STATE_EV, &ev, sizeof(ev));
|
||||||
|
}
|
||||||
|
|
||||||
|
void btp_send_gain_setting_properties_ev(struct bt_conn *conn, uint8_t units, int8_t minimum,
|
||||||
|
int8_t maximum)
|
||||||
|
{
|
||||||
|
struct btp_gain_setting_properties_ev ev;
|
||||||
|
|
||||||
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
|
|
||||||
|
ev.units = units;
|
||||||
|
ev.minimum = minimum;
|
||||||
|
ev.maximum = maximum;
|
||||||
|
|
||||||
|
tester_event(BTP_SERVICE_ID_AICS, BTP_GAIN_SETTING_PROPERTIES_EV, &ev, sizeof(ev));
|
||||||
|
}
|
||||||
|
|
||||||
|
void btp_send_aics_input_type_event(struct bt_conn *conn, uint8_t input_type)
|
||||||
|
{
|
||||||
|
struct btp_aics_input_type_ev ev;
|
||||||
|
|
||||||
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
|
|
||||||
|
ev.input_type = input_type;
|
||||||
|
|
||||||
|
tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_INPUT_TYPE_EV, &ev, sizeof(ev));
|
||||||
|
}
|
||||||
|
|
||||||
|
void btp_send_aics_status_ev(struct bt_conn *conn, bool active)
|
||||||
|
{
|
||||||
|
struct btp_aics_status_ev ev;
|
||||||
|
|
||||||
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
|
|
||||||
|
ev.active = active;
|
||||||
|
|
||||||
|
tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_STATUS_EV, &ev, sizeof(ev));
|
||||||
|
}
|
||||||
|
|
||||||
|
void btp_send_aics_description_ev(struct bt_conn *conn, uint8_t data_len, char *description)
|
||||||
|
{
|
||||||
|
struct btp_aics_description_ev *ev;
|
||||||
|
|
||||||
|
net_buf_simple_init(rx_ev_buf, 0);
|
||||||
|
|
||||||
|
ev = net_buf_simple_add(rx_ev_buf, sizeof(*ev));
|
||||||
|
|
||||||
|
bt_addr_le_copy(&ev->address, bt_conn_get_dst(conn));
|
||||||
|
|
||||||
|
ev->data_len = data_len;
|
||||||
|
memcpy(ev->data, description, data_len);
|
||||||
|
|
||||||
|
tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_DESCRIPTION_EV, ev, sizeof(*ev) + data_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_set_gain(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
const struct btp_aics_set_gain_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("AICS set gain %d", cp->gain);
|
||||||
|
|
||||||
|
if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
|
||||||
|
if (bt_aics_gain_set(aics_client_instance.aics[0], cp->gain) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_gain_set(aics_server_instance.aics[i], cp->gain) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_unmute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
const struct btp_aics_unmute_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("AICS Unmute");
|
||||||
|
|
||||||
|
if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
|
||||||
|
if (bt_aics_unmute(aics_client_instance.aics[0]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_unmute(aics_server_instance.aics[i]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_mute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
const struct btp_aics_mute_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("AICS Mute");
|
||||||
|
|
||||||
|
if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
|
||||||
|
if (bt_aics_mute(aics_client_instance.aics[0]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_mute(aics_server_instance.aics[i]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_state_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
const struct btp_aics_state_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("AICS State");
|
||||||
|
|
||||||
|
if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
|
||||||
|
if (bt_aics_state_get(aics_client_instance.aics[0]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_state_get(aics_server_instance.aics[i]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_type_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
const struct btp_aics_type_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("AICS Type");
|
||||||
|
|
||||||
|
if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
|
||||||
|
if (bt_aics_type_get(aics_client_instance.aics[0]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_type_get(aics_server_instance.aics[i]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_status_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
const struct btp_aics_status_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("AICS Status");
|
||||||
|
|
||||||
|
if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
|
||||||
|
if (bt_aics_status_get(aics_client_instance.aics[0]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_status_get(aics_server_instance.aics[i]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_gain_setting_prop_get(const void *cmd, uint16_t cmd_len, void *rsp,
|
||||||
|
uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
const struct btp_aics_gain_setting_prop_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("AICS Gain settings properties");
|
||||||
|
|
||||||
|
if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
|
||||||
|
if (bt_aics_gain_setting_get(aics_client_instance.aics[0]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_gain_setting_get(aics_server_instance.aics[i]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_man_gain_set(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
const struct btp_aics_manual_gain_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("AICS set manual gain mode");
|
||||||
|
|
||||||
|
if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
|
||||||
|
if (bt_aics_manual_gain_set(aics_client_instance.aics[0]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_manual_gain_set(aics_server_instance.aics[i]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_auto_gain_set(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
const struct btp_aics_auto_gain_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("AICS set automatic gain mode");
|
||||||
|
|
||||||
|
if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
|
||||||
|
if (bt_aics_automatic_gain_set(aics_client_instance.aics[0]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_automatic_gain_set(aics_server_instance.aics[i]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_set_man_gain_only(const void *cmd, uint16_t cmd_len, void *rsp,
|
||||||
|
uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
LOG_DBG("AICS manual gain only set");
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_gain_set_manual_only(aics_server_instance.aics[i]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_set_auto_gain_only(const void *cmd, uint16_t cmd_len, void *rsp,
|
||||||
|
uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
LOG_DBG("AICS auto gain only set");
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_gain_set_auto_only(aics_server_instance.aics[i]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_mute_disable(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
LOG_DBG("AICS disable mute");
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_disable_mute(aics_server_instance.aics[i]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_desc_set(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
const struct btp_aics_audio_desc_cmd *cp = cmd;
|
||||||
|
char description[BT_AICS_MAX_INPUT_DESCRIPTION_SIZE];
|
||||||
|
|
||||||
|
LOG_DBG("AICS set description");
|
||||||
|
|
||||||
|
if (cmd_len < sizeof(*cp) || cmd_len != sizeof(*cp) + cp->desc_len) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cp->desc_len >= sizeof(description)) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cp->desc_len > (BT_AICS_MAX_INPUT_DESCRIPTION_SIZE - 1)) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(description, cp->desc, cp->desc_len);
|
||||||
|
description[cp->desc_len] = '\0';
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_description_set(aics_server_instance.aics[i], description) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t aics_desc_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
const struct btp_aics_desc_cmd *cp = cmd;
|
||||||
|
|
||||||
|
LOG_DBG("AICS Description");
|
||||||
|
|
||||||
|
if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
|
||||||
|
if (bt_aics_description_get(aics_client_instance.aics[0]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
|
||||||
|
if (bt_aics_description_get(aics_server_instance.aics[i]) != 0) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct btp_handler aics_handlers[] = {
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_READ_SUPPORTED_COMMANDS,
|
||||||
|
.index = BTP_INDEX_NONE,
|
||||||
|
.expect_len = 0,
|
||||||
|
.func = aics_supported_commands,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_SET_GAIN,
|
||||||
|
.expect_len = sizeof(struct btp_aics_set_gain_cmd),
|
||||||
|
.func = aics_set_gain,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_MUTE,
|
||||||
|
.expect_len = sizeof(struct btp_aics_mute_cmd),
|
||||||
|
.func = aics_mute,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_UNMUTE,
|
||||||
|
.expect_len = sizeof(struct btp_aics_unmute_cmd),
|
||||||
|
.func = aics_unmute,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_GAIN_SETTING_PROP_GET,
|
||||||
|
.expect_len = sizeof(struct btp_aics_gain_setting_prop_cmd),
|
||||||
|
.func = aics_gain_setting_prop_get,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_MUTE_DISABLE,
|
||||||
|
.expect_len = 0,
|
||||||
|
.func = aics_mute_disable,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_MAN_GAIN_SET,
|
||||||
|
.expect_len = sizeof(struct btp_aics_manual_gain_cmd),
|
||||||
|
.func = aics_man_gain_set,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_AUTO_GAIN_SET,
|
||||||
|
.expect_len = sizeof(struct btp_aics_auto_gain_cmd),
|
||||||
|
.func = aics_auto_gain_set,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_SET_AUTO_GAIN_ONLY,
|
||||||
|
.expect_len = 0,
|
||||||
|
.func = aics_set_auto_gain_only,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_SET_MAN_GAIN_ONLY,
|
||||||
|
.expect_len = 0,
|
||||||
|
.func = aics_set_man_gain_only,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_AUDIO_DESCRIPTION_SET,
|
||||||
|
.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
|
||||||
|
.func = aics_desc_set,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_DESCRIPTION_GET,
|
||||||
|
.expect_len = sizeof(struct btp_aics_desc_cmd),
|
||||||
|
.func = aics_desc_get,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_TYPE_GET,
|
||||||
|
.expect_len = sizeof(struct btp_aics_type_cmd),
|
||||||
|
.func = aics_type_get,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_STATUS_GET,
|
||||||
|
.expect_len = sizeof(struct btp_aics_status_cmd),
|
||||||
|
.func = aics_status_get,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_AICS_STATE_GET,
|
||||||
|
.expect_len = sizeof(struct btp_aics_state_cmd),
|
||||||
|
.func = aics_state_get,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void aics_state_cb(struct bt_aics *inst, int err, int8_t gain, uint8_t mute, uint8_t mode)
|
||||||
|
{
|
||||||
|
struct bt_conn *conn;
|
||||||
|
|
||||||
|
bt_aics_client_conn_get(inst, &conn);
|
||||||
|
btp_send_aics_state_ev(conn, gain, mute, mode);
|
||||||
|
|
||||||
|
LOG_DBG("AICS state callback (%d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aics_gain_setting_cb(struct bt_aics *inst, int err, uint8_t units, int8_t minimum,
|
||||||
|
int8_t maximum)
|
||||||
|
{
|
||||||
|
struct bt_conn *conn;
|
||||||
|
|
||||||
|
bt_aics_client_conn_get(inst, &conn);
|
||||||
|
btp_send_gain_setting_properties_ev(conn, units, minimum, maximum);
|
||||||
|
|
||||||
|
LOG_DBG("AICS gain setting callback (%d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aics_input_type_cb(struct bt_aics *inst, int err, uint8_t input_type)
|
||||||
|
{
|
||||||
|
struct bt_conn *conn;
|
||||||
|
|
||||||
|
bt_aics_client_conn_get(inst, &conn);
|
||||||
|
btp_send_aics_input_type_event(conn, input_type);
|
||||||
|
|
||||||
|
LOG_DBG("AICS input type callback (%d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aics_status_cb(struct bt_aics *inst, int err, bool active)
|
||||||
|
{
|
||||||
|
struct bt_conn *conn;
|
||||||
|
|
||||||
|
bt_aics_client_conn_get(inst, &conn);
|
||||||
|
btp_send_aics_status_ev(conn, active);
|
||||||
|
|
||||||
|
LOG_DBG("AICS status callback (%d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aics_description_cb(struct bt_aics *inst, int err, char *description)
|
||||||
|
{
|
||||||
|
struct bt_conn *conn;
|
||||||
|
uint8_t data_len = strlen(description);
|
||||||
|
|
||||||
|
bt_aics_client_conn_get(inst, &conn);
|
||||||
|
btp_send_aics_description_ev(conn, data_len, description);
|
||||||
|
|
||||||
|
LOG_DBG("AICS description callback (%d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bt_aics_cb aics_client_cb = {
|
||||||
|
.state = aics_state_cb,
|
||||||
|
.gain_setting = aics_gain_setting_cb,
|
||||||
|
.type = aics_input_type_cb,
|
||||||
|
.status = aics_status_cb,
|
||||||
|
.description = aics_description_cb,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t tester_init_aics(void)
|
||||||
|
{
|
||||||
|
tester_register_command_handlers(BTP_SERVICE_ID_AICS, aics_handlers,
|
||||||
|
ARRAY_SIZE(aics_handlers));
|
||||||
|
|
||||||
|
return tester_init_vcs();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t tester_unregister_aics(void)
|
||||||
|
{
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
|
@ -80,6 +80,9 @@ static uint8_t supported_services(const void *cmd, uint16_t cmd_len,
|
||||||
#if defined(CONFIG_BT_CSIP_SET_MEMBER)
|
#if defined(CONFIG_BT_CSIP_SET_MEMBER)
|
||||||
tester_set_bit(rp->data, BTP_SERVICE_ID_CSIS);
|
tester_set_bit(rp->data, BTP_SERVICE_ID_CSIS);
|
||||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER */
|
#endif /* CONFIG_BT_CSIP_SET_MEMBER */
|
||||||
|
#if defined(CONFIG_BT_MICP_MIC_DEV) || defined(CONFIG_BT_MICP_MIC_CTLR)
|
||||||
|
tester_set_bit(rp->data, BTP_SERVICE_ID_MICP);
|
||||||
|
#endif /* CONFIG_BT_MICP_MIC_DEV */
|
||||||
|
|
||||||
*rsp_len = sizeof(*rp) + 2;
|
*rsp_len = sizeof(*rp) + 2;
|
||||||
|
|
||||||
|
@ -145,6 +148,9 @@ static uint8_t register_service(const void *cmd, uint16_t cmd_len,
|
||||||
case BTP_SERVICE_ID_BAP:
|
case BTP_SERVICE_ID_BAP:
|
||||||
status = tester_init_bap();
|
status = tester_init_bap();
|
||||||
break;
|
break;
|
||||||
|
case BTP_SERVICE_ID_MICP:
|
||||||
|
status = tester_init_micp();
|
||||||
|
break;
|
||||||
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT or CONFIG_BT_BAP_UNICAST_SERVER */
|
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT or CONFIG_BT_BAP_UNICAST_SERVER */
|
||||||
#if defined(CONFIG_BT_HAS)
|
#if defined(CONFIG_BT_HAS)
|
||||||
case BTP_SERVICE_ID_HAS:
|
case BTP_SERVICE_ID_HAS:
|
||||||
|
@ -228,6 +234,9 @@ static uint8_t unregister_service(const void *cmd, uint16_t cmd_len,
|
||||||
case BTP_SERVICE_ID_BAP:
|
case BTP_SERVICE_ID_BAP:
|
||||||
status = tester_unregister_bap();
|
status = tester_unregister_bap();
|
||||||
break;
|
break;
|
||||||
|
case BTP_SERVICE_ID_MICP:
|
||||||
|
status = tester_unregister_micp();
|
||||||
|
break;
|
||||||
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT or CONFIG_BT_BAP_UNICAST_SERVER */
|
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT or CONFIG_BT_BAP_UNICAST_SERVER */
|
||||||
#if defined(CONFIG_BT_HAS)
|
#if defined(CONFIG_BT_HAS)
|
||||||
case BTP_SERVICE_ID_HAS:
|
case BTP_SERVICE_ID_HAS:
|
||||||
|
|
264
tests/bluetooth/tester/src/btp_micp.c
Normal file
264
tests/bluetooth/tester/src/btp_micp.c
Normal file
|
@ -0,0 +1,264 @@
|
||||||
|
/* btp_micp.c - Bluetooth MICP Tester */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Codecoup
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
|
#include <zephyr/bluetooth/bluetooth.h>
|
||||||
|
#include <zephyr/bluetooth/audio/audio.h>
|
||||||
|
#include <zephyr/bluetooth/audio/micp.h>
|
||||||
|
#include <zephyr/bluetooth/audio/aics.h>
|
||||||
|
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/sys/byteorder.h>
|
||||||
|
|
||||||
|
#include <../../subsys/bluetooth/audio/micp_internal.h>
|
||||||
|
#include <../../subsys/bluetooth/audio/aics_internal.h>
|
||||||
|
|
||||||
|
#include "bap_endpoint.h"
|
||||||
|
#include "btp/btp.h"
|
||||||
|
|
||||||
|
#define LOG_MODULE_NAME bttester_micp
|
||||||
|
LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
|
||||||
|
|
||||||
|
static struct bt_micp_mic_ctlr *mic_ctlr;
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_MICP_MIC_CTLR_AICS)
|
||||||
|
static struct bt_micp_included micp_included;
|
||||||
|
struct chrc_handles {
|
||||||
|
uint16_t mute_handle;
|
||||||
|
uint16_t state_handle;
|
||||||
|
uint16_t gain_handle;
|
||||||
|
uint16_t type_handle;
|
||||||
|
uint16_t status_handle;
|
||||||
|
uint16_t control_handle;
|
||||||
|
uint16_t desc_handle;
|
||||||
|
};
|
||||||
|
struct chrc_handles micp_handles;
|
||||||
|
extern struct btp_aics_instance aics_client_instance;
|
||||||
|
extern struct bt_aics_cb aics_client_cb;
|
||||||
|
#endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */
|
||||||
|
|
||||||
|
static void btp_send_micp_found_ev(struct bt_conn *conn, const struct chrc_handles *micp_handles)
|
||||||
|
{
|
||||||
|
struct btp_micp_discovered_ev ev;
|
||||||
|
|
||||||
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
|
|
||||||
|
ev.mute_handle = sys_cpu_to_le16(micp_handles->mute_handle);
|
||||||
|
ev.state_handle = sys_cpu_to_le16(micp_handles->state_handle);
|
||||||
|
ev.gain_handle = sys_cpu_to_le16(micp_handles->gain_handle);
|
||||||
|
ev.type_handle = sys_cpu_to_le16(micp_handles->type_handle);
|
||||||
|
ev.status_handle = sys_cpu_to_le16(micp_handles->status_handle);
|
||||||
|
ev.control_handle = sys_cpu_to_le16(micp_handles->control_handle);
|
||||||
|
ev.desc_handle = sys_cpu_to_le16(micp_handles->desc_handle);
|
||||||
|
|
||||||
|
tester_event(BTP_SERVICE_ID_MICP, BTP_MICP_DISCOVERED_EV, &ev, sizeof(ev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void btp_send_micp_mute_state_ev(struct bt_conn *conn, uint8_t mute)
|
||||||
|
{
|
||||||
|
struct btp_micp_mute_state_ev ev;
|
||||||
|
|
||||||
|
bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
|
||||||
|
|
||||||
|
ev.mute = mute;
|
||||||
|
|
||||||
|
tester_event(BTP_SERVICE_ID_MICP, BTP_MICP_MUTE_STATE_EV, &ev, sizeof(ev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void micp_mic_ctlr_mute_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err, uint8_t mute)
|
||||||
|
{
|
||||||
|
struct bt_conn *conn;
|
||||||
|
|
||||||
|
bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn);
|
||||||
|
btp_send_micp_mute_state_ev(conn, mute);
|
||||||
|
|
||||||
|
LOG_DBG("MICP Mute cb (%d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void micp_mic_ctlr_mute_written_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err)
|
||||||
|
{
|
||||||
|
struct bt_conn *conn;
|
||||||
|
uint8_t mute_state = bt_micp_mic_ctlr_mute_get(mic_ctlr);
|
||||||
|
|
||||||
|
bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn);
|
||||||
|
btp_send_micp_mute_state_ev(conn, mute_state);
|
||||||
|
|
||||||
|
LOG_DBG("MICP Mute Written cb (%d))", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void micp_mic_ctlr_unmute_written_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err)
|
||||||
|
{
|
||||||
|
struct bt_conn *conn;
|
||||||
|
uint8_t mute_state = bt_micp_mic_ctlr_mute_get(mic_ctlr);
|
||||||
|
|
||||||
|
bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn);
|
||||||
|
btp_send_micp_mute_state_ev(conn, mute_state);
|
||||||
|
|
||||||
|
LOG_DBG("MICP Mute Unwritten cb (%d))", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void micp_mic_ctlr_discover_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err,
|
||||||
|
uint8_t aics_count)
|
||||||
|
{
|
||||||
|
struct bt_conn *conn;
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
LOG_DBG("Discovery failed (%d)", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("Discovery done with %u AICS",
|
||||||
|
aics_count);
|
||||||
|
|
||||||
|
bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn);
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_MICP_MIC_CTLR_AICS)
|
||||||
|
if (bt_micp_mic_ctlr_included_get(mic_ctlr, &micp_included) != 0) {
|
||||||
|
LOG_DBG("Could not get included services");
|
||||||
|
memset(&micp_handles, 0, sizeof(micp_handles));
|
||||||
|
} else {
|
||||||
|
aics_client_instance.aics_cnt = micp_included.aics_cnt;
|
||||||
|
aics_client_instance.aics = micp_included.aics;
|
||||||
|
bt_aics_client_cb_register(aics_client_instance.aics[0], &aics_client_cb);
|
||||||
|
|
||||||
|
micp_handles.state_handle = micp_included.aics[0]->cli.state_handle;
|
||||||
|
micp_handles.gain_handle = micp_included.aics[0]->cli.gain_handle;
|
||||||
|
micp_handles.type_handle = micp_included.aics[0]->cli.type_handle;
|
||||||
|
micp_handles.status_handle = micp_included.aics[0]->cli.status_handle;
|
||||||
|
micp_handles.control_handle = micp_included.aics[0]->cli.control_handle;
|
||||||
|
micp_handles.desc_handle = micp_included.aics[0]->cli.desc_handle;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */
|
||||||
|
|
||||||
|
micp_handles.mute_handle = mic_ctlr->mute_handle;
|
||||||
|
btp_send_micp_found_ev(conn, &micp_handles);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_micp_mic_ctlr_cb micp_cbs = {
|
||||||
|
.discover = micp_mic_ctlr_discover_cb,
|
||||||
|
.mute = micp_mic_ctlr_mute_cb,
|
||||||
|
.mute_written = micp_mic_ctlr_mute_written_cb,
|
||||||
|
.unmute_written = micp_mic_ctlr_unmute_written_cb,
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t micp_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp,
|
||||||
|
uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
struct btp_micp_read_supported_commands_rp *rp = rsp;
|
||||||
|
|
||||||
|
/* octet 0 */
|
||||||
|
tester_set_bit(rp->data, BTP_MICP_READ_SUPPORTED_COMMANDS);
|
||||||
|
tester_set_bit(rp->data, BTP_MICP_CTLR_DISCOVER);
|
||||||
|
tester_set_bit(rp->data, BTP_MICP_CTLR_MUTE_READ);
|
||||||
|
tester_set_bit(rp->data, BTP_MICP_CTLR_MUTE);
|
||||||
|
|
||||||
|
*rsp_len = sizeof(*rp) + 1;
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t micp_discover(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
const struct btp_micp_discover_cmd *cp = cmd;
|
||||||
|
struct bt_conn *conn;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
|
||||||
|
if (!conn) {
|
||||||
|
LOG_ERR("Unknown connection");
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_micp_mic_ctlr_discover(conn, &mic_ctlr);
|
||||||
|
if (err) {
|
||||||
|
LOG_DBG("Fail: %d", err);
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t micp_mute_read(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
LOG_DBG("Read mute");
|
||||||
|
|
||||||
|
err = bt_micp_mic_ctlr_mute_get(mic_ctlr);
|
||||||
|
if (err) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t micp_mute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
LOG_DBG("MICP Mute");
|
||||||
|
|
||||||
|
err = bt_micp_mic_ctlr_mute(mic_ctlr);
|
||||||
|
if (err) {
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct btp_handler micp_handlers[] = {
|
||||||
|
{
|
||||||
|
.opcode = BTP_MICP_READ_SUPPORTED_COMMANDS,
|
||||||
|
.index = BTP_INDEX_NONE,
|
||||||
|
.expect_len = 0,
|
||||||
|
.func = micp_supported_commands,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_MICP_CTLR_DISCOVER,
|
||||||
|
.expect_len = sizeof(struct btp_micp_discover_cmd),
|
||||||
|
.func = micp_discover,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_MICP_CTLR_MUTE_READ,
|
||||||
|
.expect_len = sizeof(struct btp_micp_mute_read_cmd),
|
||||||
|
.func = micp_mute_read,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.opcode = BTP_MICP_CTLR_MUTE,
|
||||||
|
.expect_len = sizeof(struct btp_micp_mute_cmd),
|
||||||
|
.func = micp_mute,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t tester_init_micp(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = bt_micp_mic_ctlr_cb_register(&micp_cbs);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
LOG_DBG("Failed to register callbacks: %d", err);
|
||||||
|
return BTP_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
tester_register_command_handlers(BTP_SERVICE_ID_MICP, micp_handlers,
|
||||||
|
ARRAY_SIZE(micp_handlers));
|
||||||
|
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t tester_unregister_micp(void)
|
||||||
|
{
|
||||||
|
(void)bt_micp_mic_ctlr_cb_register(NULL);
|
||||||
|
return BTP_STATUS_SUCCESS;
|
||||||
|
}
|
|
@ -15,6 +15,8 @@
|
||||||
#include "zephyr/bluetooth/audio/vocs.h"
|
#include "zephyr/bluetooth/audio/vocs.h"
|
||||||
#include "zephyr/sys/util.h"
|
#include "zephyr/sys/util.h"
|
||||||
|
|
||||||
|
#include <../../subsys/bluetooth/audio/micp_internal.h>
|
||||||
|
#include <../../subsys/bluetooth/audio/aics_internal.h>
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
#define LOG_MODULE_NAME bttester_vcp
|
#define LOG_MODULE_NAME bttester_vcp
|
||||||
LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
|
LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
|
||||||
|
@ -26,6 +28,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
|
||||||
|
|
||||||
static struct bt_vcp_vol_rend_register_param vcp_register_param;
|
static struct bt_vcp_vol_rend_register_param vcp_register_param;
|
||||||
static struct bt_vcp_included included;
|
static struct bt_vcp_included included;
|
||||||
|
extern struct btp_aics_instance aics_server_instance;
|
||||||
|
|
||||||
/* Volume Control Service */
|
/* Volume Control Service */
|
||||||
static uint8_t vcs_supported_commands(const void *cmd, uint16_t cmd_len,
|
static uint8_t vcs_supported_commands(const void *cmd, uint16_t cmd_len,
|
||||||
|
@ -157,265 +160,6 @@ static const struct btp_handler vcs_handlers[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Audio Input Control Service */
|
|
||||||
static uint8_t aics_supported_commands(const void *cmd, uint16_t cmd_len,
|
|
||||||
void *rsp, uint16_t *rsp_len)
|
|
||||||
{
|
|
||||||
struct btp_aics_read_supported_commands_rp *rp = rsp;
|
|
||||||
|
|
||||||
/* octet 0 */
|
|
||||||
tester_set_bit(rp->data, BTP_AICS_READ_SUPPORTED_COMMANDS);
|
|
||||||
tester_set_bit(rp->data, BTP_AICS_SET_GAIN);
|
|
||||||
tester_set_bit(rp->data, BTP_AICS_MUTE);
|
|
||||||
tester_set_bit(rp->data, BTP_AICS_UNMUTE);
|
|
||||||
tester_set_bit(rp->data, BTP_AICS_MUTE_DISABLE);
|
|
||||||
tester_set_bit(rp->data, BTP_AICS_MAN_GAIN);
|
|
||||||
tester_set_bit(rp->data, BTP_AICS_AUTO_GAIN);
|
|
||||||
tester_set_bit(rp->data, BTP_AICS_MAN_GAIN_ONLY);
|
|
||||||
tester_set_bit(rp->data, BTP_AICS_AUTO_GAIN_ONLY);
|
|
||||||
|
|
||||||
/* octet 1 */
|
|
||||||
tester_set_bit(rp->data, BTP_AICS_DESCRIPTION);
|
|
||||||
|
|
||||||
*rsp_len = sizeof(*rp) + 2;
|
|
||||||
|
|
||||||
return BTP_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void aics_state_cb(struct bt_aics *inst, int err, int8_t gain,
|
|
||||||
uint8_t mute, uint8_t mode)
|
|
||||||
{
|
|
||||||
LOG_DBG("AICS state callback (%d)", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void aics_gain_setting_cb(struct bt_aics *inst, int err, uint8_t units,
|
|
||||||
int8_t minimum, int8_t maximum)
|
|
||||||
{
|
|
||||||
LOG_DBG("AICS gain setting callback (%d)", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void aics_input_type_cb(struct bt_aics *inst, int err,
|
|
||||||
uint8_t input_type)
|
|
||||||
{
|
|
||||||
LOG_DBG("AICS input type callback (%d)", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void aics_status_cb(struct bt_aics *inst, int err, bool active)
|
|
||||||
{
|
|
||||||
LOG_DBG("AICS status callback (%d)", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void aics_description_cb(struct bt_aics *inst, int err,
|
|
||||||
char *description)
|
|
||||||
{
|
|
||||||
LOG_DBG("AICS description callback (%d)", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct bt_aics_cb aics_cb = {
|
|
||||||
.state = aics_state_cb,
|
|
||||||
.gain_setting = aics_gain_setting_cb,
|
|
||||||
.type = aics_input_type_cb,
|
|
||||||
.status = aics_status_cb,
|
|
||||||
.description = aics_description_cb
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint8_t aics_set_gain(const void *cmd, uint16_t cmd_len,
|
|
||||||
void *rsp, uint16_t *rsp_len)
|
|
||||||
{
|
|
||||||
const struct btp_aics_set_gain_cmd *cp = cmd;
|
|
||||||
|
|
||||||
LOG_DBG("AICS set gain %d", cp->gain);
|
|
||||||
|
|
||||||
for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) {
|
|
||||||
if (bt_aics_gain_set(included.aics[0], cp->gain) != 0) {
|
|
||||||
return BTP_STATUS_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return BTP_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t aics_mute(const void *cmd, uint16_t cmd_len,
|
|
||||||
void *rsp, uint16_t *rsp_len)
|
|
||||||
{
|
|
||||||
LOG_DBG("AICS mute");
|
|
||||||
|
|
||||||
for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) {
|
|
||||||
if (bt_aics_mute(included.aics[i]) != 0) {
|
|
||||||
return BTP_STATUS_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return BTP_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t aics_mute_disable(const void *cmd, uint16_t cmd_len,
|
|
||||||
void *rsp, uint16_t *rsp_len)
|
|
||||||
{
|
|
||||||
LOG_DBG("AICS mute disable");
|
|
||||||
|
|
||||||
for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) {
|
|
||||||
if (bt_aics_disable_mute(included.aics[i]) != 0) {
|
|
||||||
return BTP_STATUS_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return BTP_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t aics_unmute(const void *cmd, uint16_t cmd_len,
|
|
||||||
void *rsp, uint16_t *rsp_len)
|
|
||||||
{
|
|
||||||
LOG_DBG("AICS unmute");
|
|
||||||
|
|
||||||
for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) {
|
|
||||||
if (bt_aics_unmute(included.aics[i]) != 0) {
|
|
||||||
return BTP_STATUS_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return BTP_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t aics_man_gain(const void *cmd, uint16_t cmd_len,
|
|
||||||
void *rsp, uint16_t *rsp_len)
|
|
||||||
{
|
|
||||||
LOG_DBG("AICS manual gain set");
|
|
||||||
|
|
||||||
for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) {
|
|
||||||
if (bt_aics_manual_gain_set(included.aics[i]) != 0) {
|
|
||||||
return BTP_STATUS_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return BTP_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t aics_auto_gain(const void *cmd, uint16_t cmd_len,
|
|
||||||
void *rsp, uint16_t *rsp_len)
|
|
||||||
{
|
|
||||||
LOG_DBG("AICS auto gain set");
|
|
||||||
|
|
||||||
for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) {
|
|
||||||
if (bt_aics_automatic_gain_set(included.aics[i]) != 0) {
|
|
||||||
return BTP_STATUS_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return BTP_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t aics_auto_gain_only(const void *cmd, uint16_t cmd_len,
|
|
||||||
void *rsp, uint16_t *rsp_len)
|
|
||||||
{
|
|
||||||
LOG_DBG("AICS auto gain only set");
|
|
||||||
|
|
||||||
for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) {
|
|
||||||
if (bt_aics_gain_set_auto_only(included.aics[i]) != 0) {
|
|
||||||
return BTP_STATUS_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return BTP_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t aics_man_gain_only(const void *cmd, uint16_t cmd_len,
|
|
||||||
void *rsp, uint16_t *rsp_len)
|
|
||||||
{
|
|
||||||
LOG_DBG("AICS manual gain only set");
|
|
||||||
|
|
||||||
for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) {
|
|
||||||
if (bt_aics_gain_set_manual_only(included.aics[i]) != 0) {
|
|
||||||
return BTP_STATUS_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return BTP_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t aics_desc(const void *cmd, uint16_t cmd_len,
|
|
||||||
void *rsp, uint16_t *rsp_len)
|
|
||||||
{
|
|
||||||
const struct btp_aics_audio_desc_cmd *cp = cmd;
|
|
||||||
char description[BT_AICS_MAX_INPUT_DESCRIPTION_SIZE];
|
|
||||||
|
|
||||||
LOG_DBG("AICS description");
|
|
||||||
|
|
||||||
if (cmd_len < sizeof(*cp) ||
|
|
||||||
cmd_len != sizeof(*cp) + cp->desc_len) {
|
|
||||||
return BTP_STATUS_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cp->desc_len >= sizeof(description)) {
|
|
||||||
return BTP_STATUS_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(description, cp->desc, cp->desc_len);
|
|
||||||
description[cp->desc_len] = '\0';
|
|
||||||
|
|
||||||
for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT; i++) {
|
|
||||||
if (bt_aics_description_set(included.aics[i], description) != 0) {
|
|
||||||
return BTP_STATUS_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return BTP_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct btp_handler aics_handlers[] = {
|
|
||||||
{
|
|
||||||
.opcode = BTP_AICS_READ_SUPPORTED_COMMANDS,
|
|
||||||
.index = BTP_INDEX_NONE,
|
|
||||||
.expect_len = 0,
|
|
||||||
.func = aics_supported_commands,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.opcode = BTP_AICS_SET_GAIN,
|
|
||||||
.expect_len = sizeof(struct btp_aics_set_gain_cmd),
|
|
||||||
.func = aics_set_gain,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.opcode = BTP_AICS_MUTE,
|
|
||||||
.expect_len = 0,
|
|
||||||
.func = aics_mute,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.opcode = BTP_AICS_UNMUTE,
|
|
||||||
.expect_len = 0,
|
|
||||||
.func = aics_unmute,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.opcode = BTP_AICS_MUTE_DISABLE,
|
|
||||||
.expect_len = 0,
|
|
||||||
.func = aics_mute_disable,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.opcode = BTP_AICS_MAN_GAIN,
|
|
||||||
.expect_len = 0,
|
|
||||||
.func = aics_man_gain,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.opcode = BTP_AICS_AUTO_GAIN,
|
|
||||||
.expect_len = 0,
|
|
||||||
.func = aics_auto_gain,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.opcode = BTP_AICS_AUTO_GAIN_ONLY,
|
|
||||||
.expect_len = 0,
|
|
||||||
.func = aics_auto_gain_only,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.opcode = BTP_AICS_MAN_GAIN_ONLY,
|
|
||||||
.expect_len = 0,
|
|
||||||
.func = aics_man_gain_only,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.opcode = BTP_AICS_DESCRIPTION,
|
|
||||||
.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
|
|
||||||
.func = aics_desc,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Volume Offset Control Service */
|
/* Volume Offset Control Service */
|
||||||
static uint8_t vocs_supported_commands(const void *cmd, uint16_t cmd_len,
|
static uint8_t vocs_supported_commands(const void *cmd, uint16_t cmd_len,
|
||||||
void *rsp, uint16_t *rsp_len)
|
void *rsp, uint16_t *rsp_len)
|
||||||
|
@ -515,6 +259,44 @@ static const struct btp_handler vocs_handlers[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* AICS Callbacks */
|
||||||
|
static void aics_state_cb(struct bt_aics *inst, int err, int8_t gain,
|
||||||
|
uint8_t mute, uint8_t mode)
|
||||||
|
{
|
||||||
|
LOG_DBG("AICS state callback (%d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aics_gain_setting_cb(struct bt_aics *inst, int err, uint8_t units,
|
||||||
|
int8_t minimum, int8_t maximum)
|
||||||
|
{
|
||||||
|
LOG_DBG("AICS gain setting callback (%d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aics_input_type_cb(struct bt_aics *inst, int err,
|
||||||
|
uint8_t input_type)
|
||||||
|
{
|
||||||
|
LOG_DBG("AICS input type callback (%d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aics_status_cb(struct bt_aics *inst, int err, bool active)
|
||||||
|
{
|
||||||
|
LOG_DBG("AICS status callback (%d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aics_description_cb(struct bt_aics *inst, int err,
|
||||||
|
char *description)
|
||||||
|
{
|
||||||
|
LOG_DBG("AICS description callback (%d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bt_aics_cb aics_server_cb = {
|
||||||
|
.state = aics_state_cb,
|
||||||
|
.gain_setting = aics_gain_setting_cb,
|
||||||
|
.type = aics_input_type_cb,
|
||||||
|
.status = aics_status_cb,
|
||||||
|
.description = aics_description_cb,
|
||||||
|
};
|
||||||
|
|
||||||
/* General profile handling */
|
/* General profile handling */
|
||||||
static void set_register_params(uint8_t gain_mode)
|
static void set_register_params(uint8_t gain_mode)
|
||||||
{
|
{
|
||||||
|
@ -545,7 +327,7 @@ static void set_register_params(uint8_t gain_mode)
|
||||||
vcp_register_param.aics_param[i].units = 1;
|
vcp_register_param.aics_param[i].units = 1;
|
||||||
vcp_register_param.aics_param[i].min_gain = 0;
|
vcp_register_param.aics_param[i].min_gain = 0;
|
||||||
vcp_register_param.aics_param[i].max_gain = 100;
|
vcp_register_param.aics_param[i].max_gain = 100;
|
||||||
vcp_register_param.aics_param[i].cb = &aics_cb;
|
vcp_register_param.aics_param[i].cb = &aics_server_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
vcp_register_param.step = 1;
|
vcp_register_param.step = 1;
|
||||||
|
@ -570,6 +352,9 @@ uint8_t tester_init_vcs(void)
|
||||||
return BTP_STATUS_FAILED;
|
return BTP_STATUS_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aics_server_instance.aics_cnt = included.aics_cnt;
|
||||||
|
aics_server_instance.aics = included.aics;
|
||||||
|
|
||||||
tester_register_command_handlers(BTP_SERVICE_ID_VCS, vcs_handlers,
|
tester_register_command_handlers(BTP_SERVICE_ID_VCS, vcs_handlers,
|
||||||
ARRAY_SIZE(vcs_handlers));
|
ARRAY_SIZE(vcs_handlers));
|
||||||
|
|
||||||
|
@ -581,19 +366,6 @@ uint8_t tester_unregister_vcs(void)
|
||||||
return BTP_STATUS_SUCCESS;
|
return BTP_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t tester_init_aics(void)
|
|
||||||
{
|
|
||||||
tester_register_command_handlers(BTP_SERVICE_ID_AICS, aics_handlers,
|
|
||||||
ARRAY_SIZE(aics_handlers));
|
|
||||||
|
|
||||||
return tester_init_vcs();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t tester_unregister_aics(void)
|
|
||||||
{
|
|
||||||
return BTP_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t tester_init_vocs(void)
|
uint8_t tester_init_vocs(void)
|
||||||
{
|
{
|
||||||
tester_register_command_handlers(BTP_SERVICE_ID_VOCS, vocs_handlers,
|
tester_register_command_handlers(BTP_SERVICE_ID_VOCS, vocs_handlers,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue