Bluetooth: Audio: Vol rend use bt_vcp_vol_rend instead of bt_vcp

Use the struct bt_vcp_vol_rend instead of the more generic
`bt_vcp`.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2022-10-10 14:54:30 +02:00 committed by Carles Cufí
commit 914e96e6fe
2 changed files with 84 additions and 89 deletions

View file

@ -67,26 +67,10 @@ struct bt_vcp_vol_ctlr {
}; };
#endif /* CONFIG_BT_VCP_VOL_CTLR */ #endif /* CONFIG_BT_VCP_VOL_CTLR */
#if defined(CONFIG_BT_VCP_VOL_REND)
struct bt_vcp_server {
struct vcs_state state;
uint8_t flags;
struct bt_vcp_vol_rend_cb *cb;
uint8_t volume_step;
struct bt_gatt_service *service_p;
struct bt_vocs *vocs_insts[CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT];
struct bt_aics *aics_insts[CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT];
};
#endif /* CONFIG_BT_VCP_VOL_REND */
/* Struct used as a common type for the api */ /* Struct used as a common type for the api */
struct bt_vcp { struct bt_vcp {
bool client_instance; bool client_instance;
union { union {
#if defined(CONFIG_BT_VCP_VOL_REND)
struct bt_vcp_server srv;
#endif /* CONFIG_BT_VCP_VOL_REND */
#if defined(CONFIG_BT_VCP_VOL_CTLR) #if defined(CONFIG_BT_VCP_VOL_CTLR)
struct bt_vcp_vol_ctlr cli; struct bt_vcp_vol_ctlr cli;
#endif /* CONFIG_BT_VCP_VOL_CTLR */ #endif /* CONFIG_BT_VCP_VOL_CTLR */

View file

@ -28,13 +28,24 @@
LOG_MODULE_REGISTER(bt_vcp_vol_rend); LOG_MODULE_REGISTER(bt_vcp_vol_rend);
#define VOLUME_DOWN(current_vol) \ #define VOLUME_DOWN(current_vol) \
((uint8_t)MAX(0, (int)current_vol - vcp_inst.srv.volume_step)) ((uint8_t)MAX(0, (int)current_vol - vol_rend.volume_step))
#define VOLUME_UP(current_vol) \ #define VOLUME_UP(current_vol) \
((uint8_t)MIN(UINT8_MAX, (int)current_vol + vcp_inst.srv.volume_step)) ((uint8_t)MIN(UINT8_MAX, (int)current_vol + vol_rend.volume_step))
#define VALID_VCP_OPCODE(opcode) ((opcode) <= BT_VCP_OPCODE_MUTE) #define VALID_VCP_OPCODE(opcode) ((opcode) <= BT_VCP_OPCODE_MUTE)
static struct bt_vcp vcp_inst; struct bt_vcp_vol_rend {
struct vcs_state state;
uint8_t flags;
struct bt_vcp_vol_rend_cb *cb;
uint8_t volume_step;
struct bt_gatt_service *service_p;
struct bt_vocs *vocs_insts[CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT];
struct bt_aics *aics_insts[CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT];
};
static struct bt_vcp_vol_rend vol_rend;
static void volume_state_cfg_changed(const struct bt_gatt_attr *attr, static void volume_state_cfg_changed(const struct bt_gatt_attr *attr,
uint16_t value) uint16_t value)
@ -47,11 +58,11 @@ static ssize_t read_vol_state(struct bt_conn *conn,
uint16_t len, uint16_t offset) uint16_t len, uint16_t offset)
{ {
LOG_DBG("Volume %u, mute %u, counter %u", LOG_DBG("Volume %u, mute %u, counter %u",
vcp_inst.srv.state.volume, vcp_inst.srv.state.mute, vol_rend.state.volume, vol_rend.state.mute,
vcp_inst.srv.state.change_counter); vol_rend.state.change_counter);
return bt_gatt_attr_read(conn, attr, buf, len, offset, return bt_gatt_attr_read(conn, attr, buf, len, offset,
&vcp_inst.srv.state, sizeof(vcp_inst.srv.state)); &vol_rend.state, sizeof(vol_rend.state));
} }
static ssize_t write_vcs_control(struct bt_conn *conn, static ssize_t write_vcs_control(struct bt_conn *conn,
@ -89,71 +100,71 @@ static ssize_t write_vcs_control(struct bt_conn *conn,
LOG_DBG("Opcode %u, counter %u", opcode, cp_val->cp.counter); LOG_DBG("Opcode %u, counter %u", opcode, cp_val->cp.counter);
if (cp_val->cp.counter != vcp_inst.srv.state.change_counter) { if (cp_val->cp.counter != vol_rend.state.change_counter) {
return BT_GATT_ERR(BT_VCP_ERR_INVALID_COUNTER); return BT_GATT_ERR(BT_VCP_ERR_INVALID_COUNTER);
} }
switch (opcode) { switch (opcode) {
case BT_VCP_OPCODE_REL_VOL_DOWN: case BT_VCP_OPCODE_REL_VOL_DOWN:
LOG_DBG("Relative Volume Down (0x%x)", opcode); LOG_DBG("Relative Volume Down (0x%x)", opcode);
if (vcp_inst.srv.state.volume > 0) { if (vol_rend.state.volume > 0) {
vcp_inst.srv.state.volume = VOLUME_DOWN(vcp_inst.srv.state.volume); vol_rend.state.volume = VOLUME_DOWN(vol_rend.state.volume);
notify = true; notify = true;
} }
volume_change = true; volume_change = true;
break; break;
case BT_VCP_OPCODE_REL_VOL_UP: case BT_VCP_OPCODE_REL_VOL_UP:
LOG_DBG("Relative Volume Up (0x%x)", opcode); LOG_DBG("Relative Volume Up (0x%x)", opcode);
if (vcp_inst.srv.state.volume != UINT8_MAX) { if (vol_rend.state.volume != UINT8_MAX) {
vcp_inst.srv.state.volume = VOLUME_UP(vcp_inst.srv.state.volume); vol_rend.state.volume = VOLUME_UP(vol_rend.state.volume);
notify = true; notify = true;
} }
volume_change = true; volume_change = true;
break; break;
case BT_VCP_OPCODE_UNMUTE_REL_VOL_DOWN: case BT_VCP_OPCODE_UNMUTE_REL_VOL_DOWN:
LOG_DBG("(Unmute) relative Volume Down (0x%x)", opcode); LOG_DBG("(Unmute) relative Volume Down (0x%x)", opcode);
if (vcp_inst.srv.state.volume > 0) { if (vol_rend.state.volume > 0) {
vcp_inst.srv.state.volume = VOLUME_DOWN(vcp_inst.srv.state.volume); vol_rend.state.volume = VOLUME_DOWN(vol_rend.state.volume);
notify = true; notify = true;
} }
if (vcp_inst.srv.state.mute) { if (vol_rend.state.mute) {
vcp_inst.srv.state.mute = BT_VCP_STATE_UNMUTED; vol_rend.state.mute = BT_VCP_STATE_UNMUTED;
notify = true; notify = true;
} }
volume_change = true; volume_change = true;
break; break;
case BT_VCP_OPCODE_UNMUTE_REL_VOL_UP: case BT_VCP_OPCODE_UNMUTE_REL_VOL_UP:
LOG_DBG("(Unmute) relative Volume Up (0x%x)", opcode); LOG_DBG("(Unmute) relative Volume Up (0x%x)", opcode);
if (vcp_inst.srv.state.volume != UINT8_MAX) { if (vol_rend.state.volume != UINT8_MAX) {
vcp_inst.srv.state.volume = VOLUME_UP(vcp_inst.srv.state.volume); vol_rend.state.volume = VOLUME_UP(vol_rend.state.volume);
notify = true; notify = true;
} }
if (vcp_inst.srv.state.mute) { if (vol_rend.state.mute) {
vcp_inst.srv.state.mute = BT_VCP_STATE_UNMUTED; vol_rend.state.mute = BT_VCP_STATE_UNMUTED;
notify = true; notify = true;
} }
volume_change = true; volume_change = true;
break; break;
case BT_VCP_OPCODE_SET_ABS_VOL: case BT_VCP_OPCODE_SET_ABS_VOL:
LOG_DBG("Set Absolute Volume (0x%x): Current volume %u", LOG_DBG("Set Absolute Volume (0x%x): Current volume %u",
opcode, vcp_inst.srv.state.volume); opcode, vol_rend.state.volume);
if (vcp_inst.srv.state.volume != cp_val->volume) { if (vol_rend.state.volume != cp_val->volume) {
vcp_inst.srv.state.volume = cp_val->volume; vol_rend.state.volume = cp_val->volume;
notify = true; notify = true;
} }
volume_change = true; volume_change = true;
break; break;
case BT_VCP_OPCODE_UNMUTE: case BT_VCP_OPCODE_UNMUTE:
LOG_DBG("Unmute (0x%x)", opcode); LOG_DBG("Unmute (0x%x)", opcode);
if (vcp_inst.srv.state.mute) { if (vol_rend.state.mute) {
vcp_inst.srv.state.mute = BT_VCP_STATE_UNMUTED; vol_rend.state.mute = BT_VCP_STATE_UNMUTED;
notify = true; notify = true;
} }
break; break;
case BT_VCP_OPCODE_MUTE: case BT_VCP_OPCODE_MUTE:
LOG_DBG("Mute (0x%x)", opcode); LOG_DBG("Mute (0x%x)", opcode);
if (vcp_inst.srv.state.mute == BT_VCP_STATE_UNMUTED) { if (vol_rend.state.mute == BT_VCP_STATE_UNMUTED) {
vcp_inst.srv.state.mute = BT_VCP_STATE_MUTED; vol_rend.state.mute = BT_VCP_STATE_MUTED;
notify = true; notify = true;
} }
break; break;
@ -163,30 +174,30 @@ static ssize_t write_vcs_control(struct bt_conn *conn,
} }
if (notify) { if (notify) {
vcp_inst.srv.state.change_counter++; vol_rend.state.change_counter++;
LOG_DBG("New state: volume %u, mute %u, counter %u", LOG_DBG("New state: volume %u, mute %u, counter %u",
vcp_inst.srv.state.volume, vcp_inst.srv.state.mute, vol_rend.state.volume, vol_rend.state.mute,
vcp_inst.srv.state.change_counter); vol_rend.state.change_counter);
bt_gatt_notify_uuid(NULL, BT_UUID_VCS_STATE, bt_gatt_notify_uuid(NULL, BT_UUID_VCS_STATE,
vcp_inst.srv.service_p->attrs, vol_rend.service_p->attrs,
&vcp_inst.srv.state, sizeof(vcp_inst.srv.state)); &vol_rend.state, sizeof(vol_rend.state));
if (vcp_inst.srv.cb && vcp_inst.srv.cb->state) { if (vol_rend.cb && vol_rend.cb->state) {
vcp_inst.srv.cb->state(0, vcp_inst.srv.state.volume, vol_rend.cb->state(0, vol_rend.state.volume,
vcp_inst.srv.state.mute); vol_rend.state.mute);
} }
} }
if (volume_change && !vcp_inst.srv.flags) { if (volume_change && !vol_rend.flags) {
vcp_inst.srv.flags = 1; vol_rend.flags = 1;
bt_gatt_notify_uuid(NULL, BT_UUID_VCS_FLAGS, bt_gatt_notify_uuid(NULL, BT_UUID_VCS_FLAGS,
vcp_inst.srv.service_p->attrs, vol_rend.service_p->attrs,
&vcp_inst.srv.flags, sizeof(vcp_inst.srv.flags)); &vol_rend.flags, sizeof(vol_rend.flags));
if (vcp_inst.srv.cb && vcp_inst.srv.cb->flags) { if (vol_rend.cb && vol_rend.cb->flags) {
vcp_inst.srv.cb->flags(0, vcp_inst.srv.flags); vol_rend.cb->flags(0, vol_rend.flags);
} }
} }
return len; return len;
@ -200,9 +211,9 @@ static void flags_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
static ssize_t read_flags(struct bt_conn *conn, const struct bt_gatt_attr *attr, static ssize_t read_flags(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset) void *buf, uint16_t len, uint16_t offset)
{ {
LOG_DBG("0x%02x", vcp_inst.srv.flags); LOG_DBG("0x%02x", vol_rend.flags);
return bt_gatt_attr_read(conn, attr, buf, len, offset, &vcp_inst.srv.flags, return bt_gatt_attr_read(conn, attr, buf, len, offset, &vol_rend.flags,
sizeof(vcp_inst.srv.flags)); sizeof(vol_rend.flags));
} }
#define DUMMY_INCLUDE(i, _) BT_GATT_INCLUDE_SERVICE(NULL), #define DUMMY_INCLUDE(i, _) BT_GATT_INCLUDE_SERVICE(NULL),
@ -243,15 +254,15 @@ static int prepare_vocs_inst(struct bt_vcp_vol_rend_register_param *param)
if (bt_uuid_cmp(vcs_attrs[i].uuid, BT_UUID_GATT_INCLUDE) == 0 && if (bt_uuid_cmp(vcs_attrs[i].uuid, BT_UUID_GATT_INCLUDE) == 0 &&
!vcs_attrs[i].user_data) { !vcs_attrs[i].user_data) {
vcp_inst.srv.vocs_insts[j] = bt_vocs_free_instance_get(); vol_rend.vocs_insts[j] = bt_vocs_free_instance_get();
if (vcp_inst.srv.vocs_insts[j] == NULL) { if (vol_rend.vocs_insts[j] == NULL) {
LOG_ERR("Could not get free VOCS instances[%d]", LOG_ERR("Could not get free VOCS instances[%d]",
j); j);
return -ENOMEM; return -ENOMEM;
} }
err = bt_vocs_register(vcp_inst.srv.vocs_insts[j], err = bt_vocs_register(vol_rend.vocs_insts[j],
&param->vocs_param[j]); &param->vocs_param[j]);
if (err != 0) { if (err != 0) {
LOG_DBG("Could not register VOCS instance[%d]: %d", LOG_DBG("Could not register VOCS instance[%d]: %d",
@ -259,7 +270,7 @@ static int prepare_vocs_inst(struct bt_vcp_vol_rend_register_param *param)
return err; return err;
} }
vcs_attrs[i].user_data = bt_vocs_svc_decl_get(vcp_inst.srv.vocs_insts[j]); vcs_attrs[i].user_data = bt_vocs_svc_decl_get(vol_rend.vocs_insts[j]);
j++; j++;
if (j == CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT) { if (j == CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT) {
@ -285,15 +296,15 @@ static int prepare_aics_inst(struct bt_vcp_vol_rend_register_param *param)
for (j = 0, i = 0; i < ARRAY_SIZE(vcs_attrs); i++) { for (j = 0, i = 0; i < ARRAY_SIZE(vcs_attrs); i++) {
if (bt_uuid_cmp(vcs_attrs[i].uuid, BT_UUID_GATT_INCLUDE) == 0 && if (bt_uuid_cmp(vcs_attrs[i].uuid, BT_UUID_GATT_INCLUDE) == 0 &&
!vcs_attrs[i].user_data) { !vcs_attrs[i].user_data) {
vcp_inst.srv.aics_insts[j] = bt_aics_free_instance_get(); vol_rend.aics_insts[j] = bt_aics_free_instance_get();
if (vcp_inst.srv.aics_insts[j] == NULL) { if (vol_rend.aics_insts[j] == NULL) {
LOG_ERR("Could not get free AICS instances[%d]", LOG_ERR("Could not get free AICS instances[%d]",
j); j);
return -ENOMEM; return -ENOMEM;
} }
err = bt_aics_register(vcp_inst.srv.aics_insts[j], err = bt_aics_register(vol_rend.aics_insts[j],
&param->aics_param[j]); &param->aics_param[j]);
if (err != 0) { if (err != 0) {
LOG_DBG("Could not register AICS instance[%d]: %d", LOG_DBG("Could not register AICS instance[%d]: %d",
@ -301,7 +312,7 @@ static int prepare_aics_inst(struct bt_vcp_vol_rend_register_param *param)
return err; return err;
} }
vcs_attrs[i].user_data = bt_aics_svc_decl_get(vcp_inst.srv.aics_insts[j]); vcs_attrs[i].user_data = bt_aics_svc_decl_get(vol_rend.aics_insts[j]);
j++; j++;
LOG_DBG("AICS P %p", vcs_attrs[i].user_data); LOG_DBG("AICS P %p", vcs_attrs[i].user_data);
@ -362,17 +373,17 @@ int bt_vcp_vol_rend_register(struct bt_vcp_vol_rend_register_param *param)
} }
vcp_inst.srv.state.volume = param->volume; vol_rend.state.volume = param->volume;
vcp_inst.srv.state.mute = param->mute; vol_rend.state.mute = param->mute;
vcp_inst.srv.volume_step = param->step; vol_rend.volume_step = param->step;
vcp_inst.srv.service_p = &vcs_svc; vol_rend.service_p = &vcs_svc;
err = bt_gatt_service_register(&vcs_svc); err = bt_gatt_service_register(&vcs_svc);
if (err != 0) { if (err != 0) {
LOG_DBG("VCP service register failed: %d", err); LOG_DBG("VCP service register failed: %d", err);
} }
vcp_inst.srv.cb = param->cb; vol_rend.cb = param->cb;
registered = true; registered = true;
@ -385,11 +396,11 @@ int bt_vcp_vol_rend_included_get(struct bt_vcp_included *included)
return -EINVAL; return -EINVAL;
} }
included->vocs_cnt = ARRAY_SIZE(vcp_inst.srv.vocs_insts); included->vocs_cnt = ARRAY_SIZE(vol_rend.vocs_insts);
included->vocs = vcp_inst.srv.vocs_insts; included->vocs = vol_rend.vocs_insts;
included->aics_cnt = ARRAY_SIZE(vcp_inst.srv.aics_insts); included->aics_cnt = ARRAY_SIZE(vol_rend.aics_insts);
included->aics = vcp_inst.srv.aics_insts; included->aics = vol_rend.aics_insts;
return 0; return 0;
} }
@ -397,7 +408,7 @@ int bt_vcp_vol_rend_included_get(struct bt_vcp_included *included)
int bt_vcp_vol_rend_set_step(uint8_t volume_step) int bt_vcp_vol_rend_set_step(uint8_t volume_step)
{ {
if (volume_step > 0) { if (volume_step > 0) {
vcp_inst.srv.volume_step = volume_step; vol_rend.volume_step = volume_step;
return 0; return 0;
} else { } else {
return -EINVAL; return -EINVAL;
@ -406,9 +417,9 @@ int bt_vcp_vol_rend_set_step(uint8_t volume_step)
int bt_vcp_vol_rend_get_state(void) int bt_vcp_vol_rend_get_state(void)
{ {
if (vcp_inst.srv.cb && vcp_inst.srv.cb->state) { if (vol_rend.cb && vol_rend.cb->state) {
vcp_inst.srv.cb->state(0, vcp_inst.srv.state.volume, vol_rend.cb->state(0, vol_rend.state.volume,
vcp_inst.srv.state.mute); vol_rend.state.mute);
} }
return 0; return 0;
@ -416,8 +427,8 @@ int bt_vcp_vol_rend_get_state(void)
int bt_vcp_vol_rend_get_flags(void) int bt_vcp_vol_rend_get_flags(void)
{ {
if (vcp_inst.srv.cb && vcp_inst.srv.cb->flags) { if (vol_rend.cb && vol_rend.cb->flags) {
vcp_inst.srv.cb->flags(0, vcp_inst.srv.flags); vol_rend.cb->flags(0, vol_rend.flags);
} }
return 0; return 0;
@ -427,7 +438,7 @@ int bt_vcp_vol_rend_vol_down(void)
{ {
const struct vcs_control cp = { const struct vcs_control cp = {
.opcode = BT_VCP_OPCODE_REL_VOL_DOWN, .opcode = BT_VCP_OPCODE_REL_VOL_DOWN,
.counter = vcp_inst.srv.state.change_counter, .counter = vol_rend.state.change_counter,
}; };
int err; int err;
@ -440,7 +451,7 @@ int bt_vcp_vol_rend_vol_up(void)
{ {
const struct vcs_control cp = { const struct vcs_control cp = {
.opcode = BT_VCP_OPCODE_REL_VOL_UP, .opcode = BT_VCP_OPCODE_REL_VOL_UP,
.counter = vcp_inst.srv.state.change_counter, .counter = vol_rend.state.change_counter,
}; };
int err; int err;
@ -453,7 +464,7 @@ int bt_vcp_vol_rend_unmute_vol_down(void)
{ {
const struct vcs_control cp = { const struct vcs_control cp = {
.opcode = BT_VCP_OPCODE_UNMUTE_REL_VOL_DOWN, .opcode = BT_VCP_OPCODE_UNMUTE_REL_VOL_DOWN,
.counter = vcp_inst.srv.state.change_counter, .counter = vol_rend.state.change_counter,
}; };
int err; int err;
@ -466,7 +477,7 @@ int bt_vcp_vol_rend_unmute_vol_up(void)
{ {
const struct vcs_control cp = { const struct vcs_control cp = {
.opcode = BT_VCP_OPCODE_UNMUTE_REL_VOL_UP, .opcode = BT_VCP_OPCODE_UNMUTE_REL_VOL_UP,
.counter = vcp_inst.srv.state.change_counter, .counter = vol_rend.state.change_counter,
}; };
int err; int err;
@ -480,7 +491,7 @@ int bt_vcp_vol_rend_set_vol(uint8_t volume)
const struct vcs_control_vol cp = { const struct vcs_control_vol cp = {
.cp = { .cp = {
.opcode = BT_VCP_OPCODE_SET_ABS_VOL, .opcode = BT_VCP_OPCODE_SET_ABS_VOL,
.counter = vcp_inst.srv.state.change_counter .counter = vol_rend.state.change_counter
}, },
.volume = volume .volume = volume
}; };
@ -495,7 +506,7 @@ int bt_vcp_vol_rend_unmute(void)
{ {
const struct vcs_control cp = { const struct vcs_control cp = {
.opcode = BT_VCP_OPCODE_UNMUTE, .opcode = BT_VCP_OPCODE_UNMUTE,
.counter = vcp_inst.srv.state.change_counter, .counter = vol_rend.state.change_counter,
}; };
int err; int err;
@ -508,7 +519,7 @@ int bt_vcp_vol_rend_mute(void)
{ {
const struct vcs_control cp = { const struct vcs_control cp = {
.opcode = BT_VCP_OPCODE_MUTE, .opcode = BT_VCP_OPCODE_MUTE,
.counter = vcp_inst.srv.state.change_counter, .counter = vol_rend.state.change_counter,
}; };
int err; int err;