2022-10-11 11:38:26

by Sathish Narasimman

[permalink] [raw]
Subject: [PATCH BlueZ v3 1/3] audio/transport: Adding volume callback to media transport

Initialize set_volume and get_volume to media transport and update the
volume when media_transport_update_device_volume is called.
---
profiles/audio/transport.c | 126 +++++++++++++++++++++++++++++++++++--
1 file changed, 120 insertions(+), 6 deletions(-)

diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
index 41339da51e17..a1445cba7993 100644
--- a/profiles/audio/transport.c
+++ b/profiles/audio/transport.c
@@ -91,6 +91,7 @@ struct bap_transport {
uint8_t rtn;
uint16_t latency;
uint32_t delay;
+ int8_t volume;
};

struct media_transport {
@@ -116,6 +117,9 @@ struct media_transport {
guint id);
void (*set_state) (struct media_transport *transport,
transport_state_t state);
+ void (*set_volume) (struct media_transport *transp,
+ int8_t volume);
+ int8_t (*get_volume) (struct media_transport *transp);
GDestroyNotify destroy;
void *data;
};
@@ -769,6 +773,58 @@ error:
"Invalid arguments in method call");
}

+static gboolean volume_bap_exists(const GDBusPropertyTable *property,
+ void *data)
+{
+ struct media_transport *transport = data;
+ struct bap_transport *bap = transport->data;
+
+ return bap->volume >= 0;
+}
+
+static gboolean get_bap_volume(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct media_transport *transport = data;
+ struct bap_transport *bap = transport->data;
+ uint16_t volume = (uint16_t)bap->volume;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &volume);
+
+ return TRUE;
+}
+
+static void set_bap_volume(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, GDBusPendingPropertySet id,
+ void *data)
+{
+ struct media_transport *transport = data;
+ struct bap_transport *bap = transport->data;
+ uint16_t arg;
+ int8_t volume;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16)
+ goto error;
+
+ dbus_message_iter_get_basic(iter, &arg);
+ if (arg > INT8_MAX)
+ goto error;
+
+ g_dbus_pending_property_success(id);
+
+ volume = (int8_t)arg;
+ if (bap->volume == volume)
+ return;
+
+ /*TODO vcp_send_volume */
+ return;
+
+error:
+ g_dbus_pending_property_error(id, ERROR_INTERFACE ".InvalidArguments",
+ "Invalid arguments in method call");
+}
+
+
static gboolean endpoint_exists(const GDBusPropertyTable *property, void *data)
{
struct media_transport *transport = data;
@@ -970,6 +1026,7 @@ static const GDBusPropertyTable bap_properties[] = {
{ "Retransmissions", "y", get_retransmissions },
{ "Latency", "q", get_latency },
{ "Delay", "u", get_delay },
+ { "Volume", "q", get_bap_volume, set_bap_volume, volume_bap_exists },
{ "Endpoint", "o", get_endpoint, NULL, endpoint_exists },
{ "Location", "u", get_location },
{ "Metadata", "ay", get_metadata },
@@ -1048,6 +1105,31 @@ static void source_state_changed(struct btd_service *service,
transport_update_playing(transport, FALSE);
}

+static int8_t get_volume_a2dp(struct media_transport *transport)
+{
+ struct a2dp_transport *a2dp = transport->data;
+
+ return a2dp->volume;
+}
+
+static void set_volume_a2dp(struct media_transport *transport, int8_t volume)
+{
+ struct a2dp_transport *a2dp = transport->data;
+
+ if (volume < 0)
+ return;
+
+ /* Check if volume really changed */
+ if (a2dp->volume == volume)
+ return;
+
+ a2dp->volume = volume;
+
+ g_dbus_emit_property_changed(btd_get_dbus_connection(),
+ transport->path,
+ MEDIA_TRANSPORT_INTERFACE, "Volume");
+}
+
static int media_transport_init_source(struct media_transport *transport)
{
struct btd_service *service;
@@ -1061,6 +1143,8 @@ static int media_transport_init_source(struct media_transport *transport)

transport->resume = resume_a2dp;
transport->suspend = suspend_a2dp;
+ transport->set_volume = set_volume_a2dp;
+ transport->get_volume = get_volume_a2dp;
transport->cancel = cancel_a2dp;
transport->data = a2dp;
transport->destroy = destroy_a2dp;
@@ -1387,6 +1471,31 @@ static void free_bap(void *data)
free(bap);
}

+static void set_volume_bap(struct media_transport *transport, int8_t volume)
+{
+ struct bap_transport *bap = transport->data;
+
+ if (volume < 0)
+ return;
+
+ /* Check if volume really changed */
+ if (bap->volume == volume)
+ return;
+
+ bap->volume = volume;
+
+ g_dbus_emit_property_changed(btd_get_dbus_connection(),
+ transport->path,
+ MEDIA_TRANSPORT_INTERFACE, "Volume");
+}
+
+static int8_t get_volume_bap(struct media_transport *transport)
+{
+ struct bap_transport *bap = transport->data;
+
+ return bap->volume;
+}
+
static int media_transport_init_bap(struct media_transport *transport,
void *stream)
{
@@ -1403,6 +1512,7 @@ static int media_transport_init_bap(struct media_transport *transport,
bap->rtn = qos->rtn;
bap->latency = qos->latency;
bap->delay = qos->delay;
+ bap->volume = 127;
bap->state_id = bt_bap_state_register(bt_bap_stream_get_session(stream),
bap_state_changed,
bap_connecting,
@@ -1413,6 +1523,8 @@ static int media_transport_init_bap(struct media_transport *transport,
transport->suspend = suspend_bap;
transport->cancel = cancel_bap;
transport->set_state = set_state_bap;
+ transport->set_volume = set_volume_bap;
+ transport->get_volume = get_volume_bap;
transport->destroy = free_bap;

return 0;
@@ -1537,12 +1649,13 @@ int8_t media_transport_get_device_volume(struct btd_device *dev)
/* Attempt to locate the transport to get its volume */
for (l = transports; l; l = l->next) {
struct media_transport *transport = l->data;
+
if (transport->device != dev)
continue;

- /* Volume is A2DP only */
- if (media_endpoint_get_sep(transport->endpoint))
- return media_transport_get_volume(transport);
+ /* Get transport volume */
+ if (transport->get_volume)
+ return transport->get_volume(transport);
}

/* If transport volume doesn't exists use device_volume */
@@ -1560,12 +1673,13 @@ void media_transport_update_device_volume(struct btd_device *dev,
/* Attempt to locate the transport to set its volume */
for (l = transports; l; l = l->next) {
struct media_transport *transport = l->data;
+
if (transport->device != dev)
continue;

- /* Volume is A2DP only */
- if (media_endpoint_get_sep(transport->endpoint)) {
- media_transport_update_volume(transport, volume);
+ /* Set transport volume */
+ if (transport->set_volume) {
+ transport->set_volume(transport, volume);
return;
}
}
--
2.25.1


2022-10-11 11:38:26

by Sathish Narasimman

[permalink] [raw]
Subject: [PATCH BlueZ v3 2/3] shared/vcp: Add callback to update media volume

Add support for callback functions to update media transport volume.
Fix to register debug functions. Also invoke vcp_attached function the
right place. Fix check for existing session if available and attach.
---
src/shared/vcp.c | 139 +++++++++++++++++++++++++++++++++++++++++------
src/shared/vcp.h | 7 +++
2 files changed, 130 insertions(+), 16 deletions(-)

diff --git a/src/shared/vcp.c b/src/shared/vcp.c
index 5459cf892a7d..8e1964234338 100644
--- a/src/shared/vcp.c
+++ b/src/shared/vcp.c
@@ -41,6 +41,11 @@ struct bt_vcp_db {
struct bt_vcs *vcs;
};

+struct ev_cb {
+ const struct bt_vcp_vr_ops *ops;
+ void *data;
+};
+
typedef void (*vcp_func_t)(struct bt_vcp *vcp, bool success, uint8_t att_ecode,
const uint8_t *value, uint16_t length,
void *user_data);
@@ -89,11 +94,16 @@ struct bt_vcp {
unsigned int vstate_id;
unsigned int vflag_id;

+ unsigned int disconn_id;
struct queue *notify;
struct queue *pending;

bt_vcp_debug_func_t debug_func;
bt_vcp_destroy_func_t debug_destroy;
+
+ struct bt_vcp_vr_ops *ops;
+ struct ev_cb *cb;
+
void *debug_data;
void *user_data;
};
@@ -124,6 +134,18 @@ static struct queue *vcp_db;
static struct queue *vcp_cbs;
static struct queue *sessions;

+static void vcp_debug(struct bt_vcp *vcp, const char *format, ...)
+{
+ va_list ap;
+
+ if (!vcp || !format || !vcp->debug_func)
+ return;
+
+ va_start(ap, format);
+ util_debug_va(vcp->debug_func, vcp->debug_data, format, ap);
+ va_end(ap);
+}
+
static void *iov_pull_mem(struct iovec *iov, size_t len)
{
void *data = iov->iov_base;
@@ -183,12 +205,17 @@ static void vcp_detached(void *data, void *user_data)

void bt_vcp_detach(struct bt_vcp *vcp)
{
+ DBG(vcp, "%p", vcp);
+
if (!queue_remove(sessions, vcp))
return;

bt_gatt_client_unref(vcp->client);
vcp->client = NULL;

+ bt_att_unregister_disconnect(vcp->att, vcp->disconn_id);
+ vcp->att = NULL;
+
queue_foreach(vcp_cbs, vcp_detached, vcp);
}

@@ -267,24 +294,14 @@ void bt_vcp_unref(struct bt_vcp *vcp)
vcp_free(vcp);
}

-static void vcp_debug(struct bt_vcp *vcp, const char *format, ...)
-{
- va_list ap;
-
- if (!vcp || !format || !vcp->debug_func)
- return;
-
- va_start(ap, format);
- util_debug_va(vcp->debug_func, vcp->debug_data, format, ap);
- va_end(ap);
-}
-
static void vcp_disconnected(int err, void *user_data)
{
struct bt_vcp *vcp = user_data;

DBG(vcp, "vcp %p disconnected err %d", vcp, err);

+ vcp->disconn_id = 0;
+
bt_vcp_detach(vcp);
}

@@ -303,12 +320,9 @@ static struct bt_vcp *vcp_get_session(struct bt_att *att, struct gatt_db *db)
vcp = bt_vcp_new(db, NULL);
vcp->att = att;

- bt_att_register_disconnect(att, vcp_disconnected, vcp, NULL);
-
bt_vcp_attach(vcp, NULL);

return vcp;
-
}

static uint8_t vcs_rel_vol_down(struct bt_vcs *vcs, struct bt_vcp *vcp,
@@ -317,6 +331,7 @@ static uint8_t vcs_rel_vol_down(struct bt_vcs *vcs, struct bt_vcp *vcp,
struct bt_vcp_db *vdb;
struct vol_state *vstate;
uint8_t *change_counter;
+ struct ev_cb *cb = vcp->cb;

DBG(vcp, "Volume Down");

@@ -344,6 +359,9 @@ static uint8_t vcs_rel_vol_down(struct bt_vcs *vcs, struct bt_vcp *vcp,
vstate->vol_set = MAX((vstate->vol_set - VCP_STEP_SIZE), 0);
vstate->counter = -~vstate->counter; /*Increment Change Counter*/

+ if (cb && cb->ops && cb->ops->set_volume)
+ cb->ops->set_volume(vcp, vstate->vol_set, cb->data);
+
gatt_db_attribute_notify(vdb->vcs->vs, (void *)vstate,
sizeof(struct vol_state),
bt_vcp_get_att(vcp));
@@ -356,6 +374,7 @@ static uint8_t vcs_rel_vol_up(struct bt_vcs *vcs, struct bt_vcp *vcp,
struct bt_vcp_db *vdb;
struct vol_state *vstate;
uint8_t *change_counter;
+ struct ev_cb *cb = vcp->cb;

DBG(vcp, "Volume Up");

@@ -383,6 +402,9 @@ static uint8_t vcs_rel_vol_up(struct bt_vcs *vcs, struct bt_vcp *vcp,
vstate->vol_set = MIN((vstate->vol_set + VCP_STEP_SIZE), 255);
vstate->counter = -~vstate->counter; /*Increment Change Counter*/

+ if (cb && cb->ops && cb->ops->set_volume)
+ cb->ops->set_volume(vcp, vstate->vol_set, cb->data);
+
gatt_db_attribute_notify(vdb->vcs->vs, (void *)vstate,
sizeof(struct vol_state),
bt_vcp_get_att(vcp));
@@ -395,6 +417,7 @@ static uint8_t vcs_unmute_rel_vol_down(struct bt_vcs *vcs, struct bt_vcp *vcp,
struct bt_vcp_db *vdb;
struct vol_state *vstate;
uint8_t *change_counter;
+ struct ev_cb *cb = vcp->cb;

DBG(vcp, "Un Mute and Volume Down");

@@ -423,6 +446,9 @@ static uint8_t vcs_unmute_rel_vol_down(struct bt_vcs *vcs, struct bt_vcp *vcp,
vstate->vol_set = MAX((vstate->vol_set - VCP_STEP_SIZE), 0);
vstate->counter = -~vstate->counter; /*Increment Change Counter*/

+ if (cb && cb->ops && cb->ops->set_volume)
+ cb->ops->set_volume(vcp, vstate->vol_set, cb->data);
+
gatt_db_attribute_notify(vdb->vcs->vs, (void *)vstate,
sizeof(struct vol_state),
bt_vcp_get_att(vcp));
@@ -435,6 +461,7 @@ static uint8_t vcs_unmute_rel_vol_up(struct bt_vcs *vcs, struct bt_vcp *vcp,
struct bt_vcp_db *vdb;
struct vol_state *vstate;
uint8_t *change_counter;
+ struct ev_cb *cb = vcp->cb;

DBG(vcp, "UN Mute and Volume Up");

@@ -463,6 +490,9 @@ static uint8_t vcs_unmute_rel_vol_up(struct bt_vcs *vcs, struct bt_vcp *vcp,
vstate->vol_set = MIN((vstate->vol_set + VCP_STEP_SIZE), 255);
vstate->counter = -~vstate->counter; /*Increment Change Counter*/

+ if (cb && cb->ops && cb->ops->set_volume)
+ cb->ops->set_volume(vcp, vstate->vol_set, cb->data);
+
gatt_db_attribute_notify(vdb->vcs->vs, (void *)vstate,
sizeof(struct vol_state),
bt_vcp_get_att(vcp));
@@ -475,6 +505,7 @@ static uint8_t vcs_set_absolute_vol(struct bt_vcs *vcs, struct bt_vcp *vcp,
struct bt_vcp_db *vdb;
struct vol_state *vstate;
struct bt_vcs_ab_vol *req;
+ struct ev_cb *cb = vcp->cb;

DBG(vcp, "Set Absolute Volume");

@@ -502,6 +533,9 @@ static uint8_t vcs_set_absolute_vol(struct bt_vcs *vcs, struct bt_vcp *vcp,
vstate->vol_set = req->vol_set;
vstate->counter = -~vstate->counter; /*Increment Change Counter*/

+ if (cb && cb->ops && cb->ops->set_volume)
+ cb->ops->set_volume(vcp, vstate->vol_set, cb->data);
+
gatt_db_attribute_notify(vdb->vcs->vs, (void *)vstate,
sizeof(struct vol_state),
bt_vcp_get_att(vcp));
@@ -514,6 +548,7 @@ static uint8_t vcs_unmute(struct bt_vcs *vcs, struct bt_vcp *vcp,
struct bt_vcp_db *vdb;
struct vol_state *vstate;
uint8_t *change_counter;
+ struct ev_cb *cb = vcp->cb;

DBG(vcp, "Un Mute");

@@ -541,6 +576,9 @@ static uint8_t vcs_unmute(struct bt_vcs *vcs, struct bt_vcp *vcp,
vstate->mute = 0x00;
vstate->counter = -~vstate->counter; /*Increment Change Counter*/

+ if (cb && cb->ops && cb->ops->set_volume)
+ cb->ops->set_volume(vcp, vstate->vol_set, cb->data);
+
gatt_db_attribute_notify(vdb->vcs->vs, (void *)vstate,
sizeof(struct vol_state),
bt_vcp_get_att(vcp));
@@ -553,6 +591,7 @@ static uint8_t vcs_mute(struct bt_vcs *vcs, struct bt_vcp *vcp,
struct bt_vcp_db *vdb;
struct vol_state *vstate;
uint8_t *change_counter;
+ struct ev_cb *cb = vcp->cb;

DBG(vcp, "MUTE");

@@ -580,6 +619,13 @@ static uint8_t vcs_mute(struct bt_vcs *vcs, struct bt_vcp *vcp,
vstate->mute = 0x01;
vstate->counter = -~vstate->counter; /*Increment Change Counter*/

+ if (cb && cb->ops && cb->ops->set_volume)
+ cb->ops->set_volume(vcp, 0, cb->data);
+
+ gatt_db_attribute_notify(vdb->vcs->vs, (void *)vstate,
+ sizeof(struct vol_state),
+ bt_vcp_get_att(vcp));
+
return 0;
}

@@ -689,8 +735,10 @@ static void vcs_state_read(struct gatt_db_attribute *attrib,
void *user_data)
{
struct bt_vcs *vcs = user_data;
+ struct bt_vcp *vcp = vcp_get_session(att, vcs->vdb->db);
struct iovec iov;

+ DBG(vcp, "VCP State Read");
iov.iov_base = vcs->vstate;
iov.iov_len = sizeof(*vcs->vstate);

@@ -704,8 +752,10 @@ static void vcs_flag_read(struct gatt_db_attribute *attrib,
void *user_data)
{
struct bt_vcs *vcs = user_data;
+ struct bt_vcp *vcp = vcp_get_session(att, vcs->vdb->db);
struct iovec iov;

+ DBG(vcp, "VCP Flag Read");
iov.iov_base = &vcs->vol_flag;
iov.iov_len = sizeof(vcs->vol_flag);

@@ -868,6 +918,14 @@ bool bt_vcp_unregister(unsigned int id)
return true;
}

+static void vcp_attached(void *data, void *user_data)
+{
+ struct bt_vcp_cb *cb = data;
+ struct bt_vcp *vcp = user_data;
+
+ cb->attached(vcp, cb->user_data);
+}
+
struct bt_vcp *bt_vcp_new(struct gatt_db *ldb, struct gatt_db *rdb)
{
struct bt_vcp *vcp;
@@ -1068,6 +1126,26 @@ static unsigned int vcp_register_notify(struct bt_vcp *vcp,
return notify->id;
}

+bool bt_vcp_vr_set_ops(struct bt_vcp *vcp, struct bt_vcp_vr_ops *ops,
+ void *data)
+{
+ struct ev_cb *cb;
+
+ if (!vcp)
+ return false;
+
+ if (vcp->cb)
+ free(vcp->cb);
+
+ cb = new0(struct ev_cb, 1);
+ cb->ops = ops;
+ cb->data = data;
+
+ vcp->cb = cb;
+
+ return true;
+}
+
static void foreach_vcs_char(struct gatt_db_attribute *attr, void *user_data)
{
struct bt_vcp *vcp = user_data;
@@ -1141,25 +1219,54 @@ static void foreach_vcs_service(struct gatt_db_attribute *attr,
gatt_db_service_foreach_char(attr, foreach_vcs_char, vcp);
}

+static void vcp_attach_att(struct bt_vcp *vcp, struct bt_att *att)
+{
+ if (vcp->disconn_id) {
+ if (att == bt_vcp_get_att(vcp))
+ return;
+ bt_att_unregister_disconnect(vcp->att, vcp->disconn_id);
+ }
+
+ vcp->disconn_id = bt_att_register_disconnect(vcp->att,
+ vcp_disconnected,
+ vcp, NULL);
+}
+
bool bt_vcp_attach(struct bt_vcp *vcp, struct bt_gatt_client *client)
{
bt_uuid_t uuid;

+ if (queue_find(sessions, NULL, vcp)) {
+ /* If instance already been set but there is no client proceed
+ * to clone it otherwise considered it already attached.
+ */
+ if (client && !vcp->client)
+ goto clone;
+ return true;
+ }
+
if (!sessions)
sessions = queue_new();

queue_push_tail(sessions, vcp);

- if (!client)
+ queue_foreach(vcp_cbs, vcp_attached, vcp);
+
+ if (!client) {
+ vcp_attach_att(vcp, vcp->att);
return true;
+ }

if (vcp->client)
return false;

+clone:
vcp->client = bt_gatt_client_clone(client);
if (!vcp->client)
return false;

+ vcp_attach_att(vcp, bt_gatt_client_get_att(client));
+
bt_uuid16_create(&uuid, VCS_UUID);
gatt_db_foreach_service(vcp->ldb->db, &uuid, foreach_vcs_service, vcp);

diff --git a/src/shared/vcp.h b/src/shared/vcp.h
index 26db5732d19b..7d70aefe0089 100644
--- a/src/shared/vcp.h
+++ b/src/shared/vcp.h
@@ -33,6 +33,13 @@

struct bt_vcp;

+struct bt_vcp_vr_ops {
+ void (*set_volume)(struct bt_vcp *vcp, int8_t volume, void *data);
+};
+
+bool bt_vcp_vr_set_ops(struct bt_vcp *vcp, struct bt_vcp_vr_ops *ops,
+ void *data);
+
typedef void (*bt_vcp_destroy_func_t)(void *user_data);
typedef void (*bt_vcp_debug_func_t)(const char *str, void *user_data);
typedef void (*bt_vcp_func_t)(struct bt_vcp *vcp, void *user_data);
--
2.25.1

2022-10-11 12:47:49

by bluez.test.bot

[permalink] [raw]
Subject: RE: [BlueZ,v3,1/3] audio/transport: Adding volume callback to media transport

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=684476

---Test result---

Test Summary:
CheckPatch FAIL 2.38 seconds
GitLint PASS 1.31 seconds
Prep - Setup ELL PASS 30.54 seconds
Build - Prep PASS 0.78 seconds
Build - Configure PASS 9.45 seconds
Build - Make PASS 1039.19 seconds
Make Check PASS 12.27 seconds
Make Check w/Valgrind PASS 331.94 seconds
Make Distcheck PASS 273.49 seconds
Build w/ext ELL - Configure PASS 9.51 seconds
Build w/ext ELL - Make PASS 99.86 seconds
Incremental Build w/ patches PASS 350.20 seconds
Scan Build PASS 642.82 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script with rule in .checkpatch.conf
Output:
[BlueZ,v3,1/3] audio/transport: Adding volume callback to media transport
WARNING:SPACING: Unnecessary space before function pointer arguments
#87: FILE: profiles/audio/transport.c:120:
+ void (*set_volume) (struct media_transport *transp,

WARNING:SPACING: Unnecessary space before function pointer arguments
#89: FILE: profiles/audio/transport.c:122:
+ int8_t (*get_volume) (struct media_transport *transp);

/github/workspace/src/13003868.patch total: 0 errors, 2 warnings, 198 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/13003868.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.




---
Regards,
Linux Bluetooth

2022-10-11 19:47:31

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH BlueZ v3 1/3] audio/transport: Adding volume callback to media transport

Hi Sathish,

On Tue, Oct 11, 2022 at 4:38 AM Sathish Narasimman
<[email protected]> wrote:
>
> Initialize set_volume and get_volume to media transport and update the
> volume when media_transport_update_device_volume is called.
> ---
> profiles/audio/transport.c | 126 +++++++++++++++++++++++++++++++++++--
> 1 file changed, 120 insertions(+), 6 deletions(-)
>
> diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
> index 41339da51e17..a1445cba7993 100644
> --- a/profiles/audio/transport.c
> +++ b/profiles/audio/transport.c
> @@ -91,6 +91,7 @@ struct bap_transport {
> uint8_t rtn;
> uint16_t latency;
> uint32_t delay;
> + int8_t volume;
> };
>
> struct media_transport {
> @@ -116,6 +117,9 @@ struct media_transport {
> guint id);
> void (*set_state) (struct media_transport *transport,
> transport_state_t state);
> + void (*set_volume) (struct media_transport *transp,
> + int8_t volume);
> + int8_t (*get_volume) (struct media_transport *transp);
> GDestroyNotify destroy;
> void *data;
> };
> @@ -769,6 +773,58 @@ error:
> "Invalid arguments in method call");
> }
>
> +static gboolean volume_bap_exists(const GDBusPropertyTable *property,
> + void *data)
> +{
> + struct media_transport *transport = data;
> + struct bap_transport *bap = transport->data;
> +
> + return bap->volume >= 0;
> +}
> +
> +static gboolean get_bap_volume(const GDBusPropertyTable *property,
> + DBusMessageIter *iter, void *data)
> +{
> + struct media_transport *transport = data;
> + struct bap_transport *bap = transport->data;
> + uint16_t volume = (uint16_t)bap->volume;
> +
> + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &volume);
> +
> + return TRUE;
> +}
> +
> +static void set_bap_volume(const GDBusPropertyTable *property,
> + DBusMessageIter *iter, GDBusPendingPropertySet id,
> + void *data)
> +{
> + struct media_transport *transport = data;
> + struct bap_transport *bap = transport->data;
> + uint16_t arg;
> + int8_t volume;
> +
> + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16)
> + goto error;
> +
> + dbus_message_iter_get_basic(iter, &arg);
> + if (arg > INT8_MAX)
> + goto error;
> +
> + g_dbus_pending_property_success(id);
> +
> + volume = (int8_t)arg;
> + if (bap->volume == volume)
> + return;
> +
> + /*TODO vcp_send_volume */

What is this TODO item for? Can we complete it right now? Afaik we
should be able to handle local changes and notify it to remote peers
or that is not how VCP works?

> + return;
> +
> +error:
> + g_dbus_pending_property_error(id, ERROR_INTERFACE ".InvalidArguments",
> + "Invalid arguments in method call");
> +}
> +
> +
> static gboolean endpoint_exists(const GDBusPropertyTable *property, void *data)
> {
> struct media_transport *transport = data;
> @@ -970,6 +1026,7 @@ static const GDBusPropertyTable bap_properties[] = {
> { "Retransmissions", "y", get_retransmissions },
> { "Latency", "q", get_latency },
> { "Delay", "u", get_delay },
> + { "Volume", "q", get_bap_volume, set_bap_volume, volume_bap_exists },

Now that we have set_volume/get_volume as callbacks these could be
changed to use them instead of having dedicated callback like abouve,
something like:

https://gist.github.com/Vudentz/19edcf96735567c1f7437a5e1dee7e04

> { "Endpoint", "o", get_endpoint, NULL, endpoint_exists },
> { "Location", "u", get_location },
> { "Metadata", "ay", get_metadata },
> @@ -1048,6 +1105,31 @@ static void source_state_changed(struct btd_service *service,
> transport_update_playing(transport, FALSE);
> }
>
> +static int8_t get_volume_a2dp(struct media_transport *transport)
> +{
> + struct a2dp_transport *a2dp = transport->data;
> +
> + return a2dp->volume;
> +}
> +
> +static void set_volume_a2dp(struct media_transport *transport, int8_t volume)
> +{
> + struct a2dp_transport *a2dp = transport->data;
> +
> + if (volume < 0)
> + return;
> +
> + /* Check if volume really changed */
> + if (a2dp->volume == volume)
> + return;
> +
> + a2dp->volume = volume;
> +
> + g_dbus_emit_property_changed(btd_get_dbus_connection(),
> + transport->path,
> + MEDIA_TRANSPORT_INTERFACE, "Volume");
> +}
> +
> static int media_transport_init_source(struct media_transport *transport)
> {
> struct btd_service *service;
> @@ -1061,6 +1143,8 @@ static int media_transport_init_source(struct media_transport *transport)
>
> transport->resume = resume_a2dp;
> transport->suspend = suspend_a2dp;
> + transport->set_volume = set_volume_a2dp;
> + transport->get_volume = get_volume_a2dp;
> transport->cancel = cancel_a2dp;
> transport->data = a2dp;
> transport->destroy = destroy_a2dp;
> @@ -1387,6 +1471,31 @@ static void free_bap(void *data)
> free(bap);
> }
>
> +static void set_volume_bap(struct media_transport *transport, int8_t volume)
> +{
> + struct bap_transport *bap = transport->data;
> +
> + if (volume < 0)
> + return;
> +
> + /* Check if volume really changed */
> + if (bap->volume == volume)
> + return;
> +
> + bap->volume = volume;
> +
> + g_dbus_emit_property_changed(btd_get_dbus_connection(),
> + transport->path,
> + MEDIA_TRANSPORT_INTERFACE, "Volume");
> +}
> +
> +static int8_t get_volume_bap(struct media_transport *transport)
> +{
> + struct bap_transport *bap = transport->data;
> +
> + return bap->volume;
> +}
> +
> static int media_transport_init_bap(struct media_transport *transport,
> void *stream)
> {
> @@ -1403,6 +1512,7 @@ static int media_transport_init_bap(struct media_transport *transport,
> bap->rtn = qos->rtn;
> bap->latency = qos->latency;
> bap->delay = qos->delay;
> + bap->volume = 127;
> bap->state_id = bt_bap_state_register(bt_bap_stream_get_session(stream),
> bap_state_changed,
> bap_connecting,
> @@ -1413,6 +1523,8 @@ static int media_transport_init_bap(struct media_transport *transport,
> transport->suspend = suspend_bap;
> transport->cancel = cancel_bap;
> transport->set_state = set_state_bap;
> + transport->set_volume = set_volume_bap;
> + transport->get_volume = get_volume_bap;
> transport->destroy = free_bap;
>
> return 0;
> @@ -1537,12 +1649,13 @@ int8_t media_transport_get_device_volume(struct btd_device *dev)
> /* Attempt to locate the transport to get its volume */
> for (l = transports; l; l = l->next) {
> struct media_transport *transport = l->data;
> +
> if (transport->device != dev)
> continue;
>
> - /* Volume is A2DP only */
> - if (media_endpoint_get_sep(transport->endpoint))
> - return media_transport_get_volume(transport);
> + /* Get transport volume */
> + if (transport->get_volume)
> + return transport->get_volume(transport);
> }
>
> /* If transport volume doesn't exists use device_volume */
> @@ -1560,12 +1673,13 @@ void media_transport_update_device_volume(struct btd_device *dev,
> /* Attempt to locate the transport to set its volume */
> for (l = transports; l; l = l->next) {
> struct media_transport *transport = l->data;
> +
> if (transport->device != dev)
> continue;
>
> - /* Volume is A2DP only */
> - if (media_endpoint_get_sep(transport->endpoint)) {
> - media_transport_update_volume(transport, volume);
> + /* Set transport volume */
> + if (transport->set_volume) {
> + transport->set_volume(transport, volume);
> return;
> }
> }
> --
> 2.25.1
>


--
Luiz Augusto von Dentz

2022-10-12 05:57:27

by Sathish Narasimman

[permalink] [raw]
Subject: Re: [PATCH BlueZ v3 1/3] audio/transport: Adding volume callback to media transport

Hi Luiz

On Wed, Oct 12, 2022 at 1:28 AM Luiz Augusto von Dentz
<[email protected]> wrote:
>
> Hi Sathish,
>
> On Tue, Oct 11, 2022 at 4:38 AM Sathish Narasimman
> <[email protected]> wrote:
> >
> > Initialize set_volume and get_volume to media transport and update the
> > volume when media_transport_update_device_volume is called.
> > ---
> > profiles/audio/transport.c | 126 +++++++++++++++++++++++++++++++++++--
> > 1 file changed, 120 insertions(+), 6 deletions(-)
> >
> > diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
> > index 41339da51e17..a1445cba7993 100644
> > --- a/profiles/audio/transport.c
> > +++ b/profiles/audio/transport.c
> > @@ -91,6 +91,7 @@ struct bap_transport {
> > uint8_t rtn;
> > uint16_t latency;
> > uint32_t delay;
> > + int8_t volume;
> > };
> >
> > struct media_transport {
> > @@ -116,6 +117,9 @@ struct media_transport {
> > guint id);
> > void (*set_state) (struct media_transport *transport,
> > transport_state_t state);
> > + void (*set_volume) (struct media_transport *transp,
> > + int8_t volume);
> > + int8_t (*get_volume) (struct media_transport *transp);
> > GDestroyNotify destroy;
> > void *data;
> > };
> > @@ -769,6 +773,58 @@ error:
> > "Invalid arguments in method call");
> > }
> >
> > +static gboolean volume_bap_exists(const GDBusPropertyTable *property,
> > + void *data)
> > +{
> > + struct media_transport *transport = data;
> > + struct bap_transport *bap = transport->data;
> > +
> > + return bap->volume >= 0;
> > +}
> > +
> > +static gboolean get_bap_volume(const GDBusPropertyTable *property,
> > + DBusMessageIter *iter, void *data)
> > +{
> > + struct media_transport *transport = data;
> > + struct bap_transport *bap = transport->data;
> > + uint16_t volume = (uint16_t)bap->volume;
> > +
> > + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &volume);
> > +
> > + return TRUE;
> > +}
> > +
> > +static void set_bap_volume(const GDBusPropertyTable *property,
> > + DBusMessageIter *iter, GDBusPendingPropertySet id,
> > + void *data)
> > +{
> > + struct media_transport *transport = data;
> > + struct bap_transport *bap = transport->data;
> > + uint16_t arg;
> > + int8_t volume;
> > +
> > + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16)
> > + goto error;
> > +
> > + dbus_message_iter_get_basic(iter, &arg);
> > + if (arg > INT8_MAX)
> > + goto error;
> > +
> > + g_dbus_pending_property_success(id);
> > +
> > + volume = (int8_t)arg;
> > + if (bap->volume == volume)
> > + return;
> > +
> > + /*TODO vcp_send_volume */
>
> What is this TODO item for? Can we complete it right now? Afaik we
> should be able to handle local changes and notify it to remote peers
> or that is not how VCP works?

The TODO part is for VCP Client. At present only VCP Server is implemented.
Whenever there is a change in volume locally we have to notify to the remote
peer in case of server Role(Volume renderer).

>
> > + return;
> > +
> > +error:
> > + g_dbus_pending_property_error(id, ERROR_INTERFACE ".InvalidArguments",
> > + "Invalid arguments in method call");
> > +}
> > +
> > +
> > static gboolean endpoint_exists(const GDBusPropertyTable *property, void *data)
> > {
> > struct media_transport *transport = data;
> > @@ -970,6 +1026,7 @@ static const GDBusPropertyTable bap_properties[] = {
> > { "Retransmissions", "y", get_retransmissions },
> > { "Latency", "q", get_latency },
> > { "Delay", "u", get_delay },
> > + { "Volume", "q", get_bap_volume, set_bap_volume, volume_bap_exists },
>
> Now that we have set_volume/get_volume as callbacks these could be
> changed to use them instead of having dedicated callback like abouve,
> something like:
>
> https://gist.github.com/Vudentz/19edcf96735567c1f7437a5e1dee7e04
>
will check and update
> > { "Endpoint", "o", get_endpoint, NULL, endpoint_exists },
> > { "Location", "u", get_location },
> > { "Metadata", "ay", get_metadata },
> > @@ -1048,6 +1105,31 @@ static void source_state_changed(struct btd_service *service,
> > transport_update_playing(transport, FALSE);
> > }
> >
> > +static int8_t get_volume_a2dp(struct media_transport *transport)
> > +{
> > + struct a2dp_transport *a2dp = transport->data;
> > +
> > + return a2dp->volume;
> > +}
> > +
> > +static void set_volume_a2dp(struct media_transport *transport, int8_t volume)
> > +{
> > + struct a2dp_transport *a2dp = transport->data;
> > +
> > + if (volume < 0)
> > + return;
> > +
> > + /* Check if volume really changed */
> > + if (a2dp->volume == volume)
> > + return;
> > +
> > + a2dp->volume = volume;
> > +
> > + g_dbus_emit_property_changed(btd_get_dbus_connection(),
> > + transport->path,
> > + MEDIA_TRANSPORT_INTERFACE, "Volume");
> > +}
> > +
> > static int media_transport_init_source(struct media_transport *transport)
> > {
> > struct btd_service *service;
> > @@ -1061,6 +1143,8 @@ static int media_transport_init_source(struct media_transport *transport)
> >
> > transport->resume = resume_a2dp;
> > transport->suspend = suspend_a2dp;
> > + transport->set_volume = set_volume_a2dp;
> > + transport->get_volume = get_volume_a2dp;
> > transport->cancel = cancel_a2dp;
> > transport->data = a2dp;
> > transport->destroy = destroy_a2dp;
> > @@ -1387,6 +1471,31 @@ static void free_bap(void *data)
> > free(bap);
> > }
> >
> > +static void set_volume_bap(struct media_transport *transport, int8_t volume)
> > +{
> > + struct bap_transport *bap = transport->data;
> > +
> > + if (volume < 0)
> > + return;
> > +
> > + /* Check if volume really changed */
> > + if (bap->volume == volume)
> > + return;
> > +
> > + bap->volume = volume;
> > +
> > + g_dbus_emit_property_changed(btd_get_dbus_connection(),
> > + transport->path,
> > + MEDIA_TRANSPORT_INTERFACE, "Volume");
> > +}
> > +
> > +static int8_t get_volume_bap(struct media_transport *transport)
> > +{
> > + struct bap_transport *bap = transport->data;
> > +
> > + return bap->volume;
> > +}
> > +
> > static int media_transport_init_bap(struct media_transport *transport,
> > void *stream)
> > {
> > @@ -1403,6 +1512,7 @@ static int media_transport_init_bap(struct media_transport *transport,
> > bap->rtn = qos->rtn;
> > bap->latency = qos->latency;
> > bap->delay = qos->delay;
> > + bap->volume = 127;
> > bap->state_id = bt_bap_state_register(bt_bap_stream_get_session(stream),
> > bap_state_changed,
> > bap_connecting,
> > @@ -1413,6 +1523,8 @@ static int media_transport_init_bap(struct media_transport *transport,
> > transport->suspend = suspend_bap;
> > transport->cancel = cancel_bap;
> > transport->set_state = set_state_bap;
> > + transport->set_volume = set_volume_bap;
> > + transport->get_volume = get_volume_bap;
> > transport->destroy = free_bap;
> >
> > return 0;
> > @@ -1537,12 +1649,13 @@ int8_t media_transport_get_device_volume(struct btd_device *dev)
> > /* Attempt to locate the transport to get its volume */
> > for (l = transports; l; l = l->next) {
> > struct media_transport *transport = l->data;
> > +
> > if (transport->device != dev)
> > continue;
> >
> > - /* Volume is A2DP only */
> > - if (media_endpoint_get_sep(transport->endpoint))
> > - return media_transport_get_volume(transport);
> > + /* Get transport volume */
> > + if (transport->get_volume)
> > + return transport->get_volume(transport);
> > }
> >
> > /* If transport volume doesn't exists use device_volume */
> > @@ -1560,12 +1673,13 @@ void media_transport_update_device_volume(struct btd_device *dev,
> > /* Attempt to locate the transport to set its volume */
> > for (l = transports; l; l = l->next) {
> > struct media_transport *transport = l->data;
> > +
> > if (transport->device != dev)
> > continue;
> >
> > - /* Volume is A2DP only */
> > - if (media_endpoint_get_sep(transport->endpoint)) {
> > - media_transport_update_volume(transport, volume);
> > + /* Set transport volume */
> > + if (transport->set_volume) {
> > + transport->set_volume(transport, volume);
> > return;
> > }
> > }
> > --
> > 2.25.1
> >
>
>
> --
> Luiz Augusto von Dentz

Sathish N

2022-10-12 19:30:32

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH BlueZ v3 1/3] audio/transport: Adding volume callback to media transport

Hi Sathish,

On Tue, Oct 11, 2022 at 10:42 PM Sathish Narasimman
<[email protected]> wrote:
>
> Hi Luiz
>
> On Wed, Oct 12, 2022 at 1:28 AM Luiz Augusto von Dentz
> <[email protected]> wrote:
> >
> > Hi Sathish,
> >
> > On Tue, Oct 11, 2022 at 4:38 AM Sathish Narasimman
> > <[email protected]> wrote:
> > >
> > > Initialize set_volume and get_volume to media transport and update the
> > > volume when media_transport_update_device_volume is called.
> > > ---
> > > profiles/audio/transport.c | 126 +++++++++++++++++++++++++++++++++++--
> > > 1 file changed, 120 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
> > > index 41339da51e17..a1445cba7993 100644
> > > --- a/profiles/audio/transport.c
> > > +++ b/profiles/audio/transport.c
> > > @@ -91,6 +91,7 @@ struct bap_transport {
> > > uint8_t rtn;
> > > uint16_t latency;
> > > uint32_t delay;
> > > + int8_t volume;
> > > };
> > >
> > > struct media_transport {
> > > @@ -116,6 +117,9 @@ struct media_transport {
> > > guint id);
> > > void (*set_state) (struct media_transport *transport,
> > > transport_state_t state);
> > > + void (*set_volume) (struct media_transport *transp,
> > > + int8_t volume);
> > > + int8_t (*get_volume) (struct media_transport *transp);
> > > GDestroyNotify destroy;
> > > void *data;
> > > };
> > > @@ -769,6 +773,58 @@ error:
> > > "Invalid arguments in method call");
> > > }
> > >
> > > +static gboolean volume_bap_exists(const GDBusPropertyTable *property,
> > > + void *data)
> > > +{
> > > + struct media_transport *transport = data;
> > > + struct bap_transport *bap = transport->data;
> > > +
> > > + return bap->volume >= 0;
> > > +}
> > > +
> > > +static gboolean get_bap_volume(const GDBusPropertyTable *property,
> > > + DBusMessageIter *iter, void *data)
> > > +{
> > > + struct media_transport *transport = data;
> > > + struct bap_transport *bap = transport->data;
> > > + uint16_t volume = (uint16_t)bap->volume;
> > > +
> > > + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &volume);
> > > +
> > > + return TRUE;
> > > +}
> > > +
> > > +static void set_bap_volume(const GDBusPropertyTable *property,
> > > + DBusMessageIter *iter, GDBusPendingPropertySet id,
> > > + void *data)
> > > +{
> > > + struct media_transport *transport = data;
> > > + struct bap_transport *bap = transport->data;
> > > + uint16_t arg;
> > > + int8_t volume;
> > > +
> > > + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16)
> > > + goto error;
> > > +
> > > + dbus_message_iter_get_basic(iter, &arg);
> > > + if (arg > INT8_MAX)
> > > + goto error;
> > > +
> > > + g_dbus_pending_property_success(id);
> > > +
> > > + volume = (int8_t)arg;
> > > + if (bap->volume == volume)
> > > + return;
> > > +
> > > + /*TODO vcp_send_volume */
> >
> > What is this TODO item for? Can we complete it right now? Afaik we
> > should be able to handle local changes and notify it to remote peers
> > or that is not how VCP works?
>
> The TODO part is for VCP Client. At present only VCP Server is implemented.
> Whenever there is a change in volume locally we have to notify to the remote
> peer in case of server Role(Volume renderer).

Well the callback to Volume property shall in case of the server
notify then, otherwise the client has no idea anything has happened,
so I think we need to implement procedure anyway handling the
distinction of client/server internally.

> >
> > > + return;
> > > +
> > > +error:
> > > + g_dbus_pending_property_error(id, ERROR_INTERFACE ".InvalidArguments",
> > > + "Invalid arguments in method call");
> > > +}
> > > +
> > > +
> > > static gboolean endpoint_exists(const GDBusPropertyTable *property, void *data)
> > > {
> > > struct media_transport *transport = data;
> > > @@ -970,6 +1026,7 @@ static const GDBusPropertyTable bap_properties[] = {
> > > { "Retransmissions", "y", get_retransmissions },
> > > { "Latency", "q", get_latency },
> > > { "Delay", "u", get_delay },
> > > + { "Volume", "q", get_bap_volume, set_bap_volume, volume_bap_exists },
> >
> > Now that we have set_volume/get_volume as callbacks these could be
> > changed to use them instead of having dedicated callback like abouve,
> > something like:
> >
> > https://gist.github.com/Vudentz/19edcf96735567c1f7437a5e1dee7e04
> >
> will check and update
> > > { "Endpoint", "o", get_endpoint, NULL, endpoint_exists },
> > > { "Location", "u", get_location },
> > > { "Metadata", "ay", get_metadata },
> > > @@ -1048,6 +1105,31 @@ static void source_state_changed(struct btd_service *service,
> > > transport_update_playing(transport, FALSE);
> > > }
> > >
> > > +static int8_t get_volume_a2dp(struct media_transport *transport)
> > > +{
> > > + struct a2dp_transport *a2dp = transport->data;
> > > +
> > > + return a2dp->volume;
> > > +}
> > > +
> > > +static void set_volume_a2dp(struct media_transport *transport, int8_t volume)
> > > +{
> > > + struct a2dp_transport *a2dp = transport->data;
> > > +
> > > + if (volume < 0)
> > > + return;
> > > +
> > > + /* Check if volume really changed */
> > > + if (a2dp->volume == volume)
> > > + return;
> > > +
> > > + a2dp->volume = volume;
> > > +
> > > + g_dbus_emit_property_changed(btd_get_dbus_connection(),
> > > + transport->path,
> > > + MEDIA_TRANSPORT_INTERFACE, "Volume");
> > > +}
> > > +
> > > static int media_transport_init_source(struct media_transport *transport)
> > > {
> > > struct btd_service *service;
> > > @@ -1061,6 +1143,8 @@ static int media_transport_init_source(struct media_transport *transport)
> > >
> > > transport->resume = resume_a2dp;
> > > transport->suspend = suspend_a2dp;
> > > + transport->set_volume = set_volume_a2dp;
> > > + transport->get_volume = get_volume_a2dp;
> > > transport->cancel = cancel_a2dp;
> > > transport->data = a2dp;
> > > transport->destroy = destroy_a2dp;
> > > @@ -1387,6 +1471,31 @@ static void free_bap(void *data)
> > > free(bap);
> > > }
> > >
> > > +static void set_volume_bap(struct media_transport *transport, int8_t volume)
> > > +{
> > > + struct bap_transport *bap = transport->data;
> > > +
> > > + if (volume < 0)
> > > + return;
> > > +
> > > + /* Check if volume really changed */
> > > + if (bap->volume == volume)
> > > + return;
> > > +
> > > + bap->volume = volume;
> > > +
> > > + g_dbus_emit_property_changed(btd_get_dbus_connection(),
> > > + transport->path,
> > > + MEDIA_TRANSPORT_INTERFACE, "Volume");
> > > +}
> > > +
> > > +static int8_t get_volume_bap(struct media_transport *transport)
> > > +{
> > > + struct bap_transport *bap = transport->data;
> > > +
> > > + return bap->volume;
> > > +}
> > > +
> > > static int media_transport_init_bap(struct media_transport *transport,
> > > void *stream)
> > > {
> > > @@ -1403,6 +1512,7 @@ static int media_transport_init_bap(struct media_transport *transport,
> > > bap->rtn = qos->rtn;
> > > bap->latency = qos->latency;
> > > bap->delay = qos->delay;
> > > + bap->volume = 127;
> > > bap->state_id = bt_bap_state_register(bt_bap_stream_get_session(stream),
> > > bap_state_changed,
> > > bap_connecting,
> > > @@ -1413,6 +1523,8 @@ static int media_transport_init_bap(struct media_transport *transport,
> > > transport->suspend = suspend_bap;
> > > transport->cancel = cancel_bap;
> > > transport->set_state = set_state_bap;
> > > + transport->set_volume = set_volume_bap;
> > > + transport->get_volume = get_volume_bap;
> > > transport->destroy = free_bap;
> > >
> > > return 0;
> > > @@ -1537,12 +1649,13 @@ int8_t media_transport_get_device_volume(struct btd_device *dev)
> > > /* Attempt to locate the transport to get its volume */
> > > for (l = transports; l; l = l->next) {
> > > struct media_transport *transport = l->data;
> > > +
> > > if (transport->device != dev)
> > > continue;
> > >
> > > - /* Volume is A2DP only */
> > > - if (media_endpoint_get_sep(transport->endpoint))
> > > - return media_transport_get_volume(transport);
> > > + /* Get transport volume */
> > > + if (transport->get_volume)
> > > + return transport->get_volume(transport);
> > > }
> > >
> > > /* If transport volume doesn't exists use device_volume */
> > > @@ -1560,12 +1673,13 @@ void media_transport_update_device_volume(struct btd_device *dev,
> > > /* Attempt to locate the transport to set its volume */
> > > for (l = transports; l; l = l->next) {
> > > struct media_transport *transport = l->data;
> > > +
> > > if (transport->device != dev)
> > > continue;
> > >
> > > - /* Volume is A2DP only */
> > > - if (media_endpoint_get_sep(transport->endpoint)) {
> > > - media_transport_update_volume(transport, volume);
> > > + /* Set transport volume */
> > > + if (transport->set_volume) {
> > > + transport->set_volume(transport, volume);
> > > return;
> > > }
> > > }
> > > --
> > > 2.25.1
> > >
> >
> >
> > --
> > Luiz Augusto von Dentz
>
> Sathish N



--
Luiz Augusto von Dentz