2022-10-07 06:26:49

by Sathish Narasimman

[permalink] [raw]
Subject: [PATCH BlueZ v2 1/3] audio/transport: Add volume callback to BAP transport

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

diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
index 41339da51e17..46b936c965bf 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_vol)(struct media_transport *transport,
+ int8_t volume);
+ int8_t (*get_vol)(struct media_transport *transport);
GDestroyNotify destroy;
void *data;
};
@@ -717,6 +721,7 @@ static gboolean volume_exists(const GDBusPropertyTable *property, void *data)
return a2dp->volume >= 0;
}

+
static gboolean get_volume(const GDBusPropertyTable *property,
DBusMessageIter *iter, void *data)
{
@@ -769,6 +774,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 +1027,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 },
@@ -1387,6 +1445,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 +1486,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 +1497,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_vol = set_volume_bap;
+ transport->get_vol = get_volume_bap;
transport->destroy = free_bap;

return 0;
@@ -1537,6 +1623,11 @@ 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;
+
+ /* Get BAP transport volume */
+ if (transport->get_vol)
+ return transport->get_vol(transport);
+
if (transport->device != dev)
continue;

@@ -1560,6 +1651,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;
+
+ /* Set BAP transport volume */
+ if (transport->set_vol) {
+ transport->set_vol(transport, volume);
+ return;
+ }
+
if (transport->device != dev)
continue;

--
2.25.1


2022-10-07 06:31:49

by Sathish Narasimman

[permalink] [raw]
Subject: [PATCH BlueZ v2 3/3] profiles: Register callback function to update volume

Callback function has to be registered to call
media_transport_update_device_volume to change transport volume.
---
profiles/audio/vcp.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)

diff --git a/profiles/audio/vcp.c b/profiles/audio/vcp.c
index b42b0a4f79dd..4b790b03c032 100644
--- a/profiles/audio/vcp.c
+++ b/profiles/audio/vcp.c
@@ -50,6 +50,7 @@
#include "src/service.h"
#include "src/log.h"
#include "src/error.h"
+#include "transport.h"

#define VCS_UUID_STR "00001844-0000-1000-8000-00805f9b34fb"
#define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint1"
@@ -83,6 +84,20 @@ static struct vcp_data *vcp_data_new(struct btd_device *device)
return data;
}

+static void vr_set_volume(struct bt_vcp *vcp, int8_t volume, void *data)
+{
+ struct vcp_data *user_data = data;
+ struct btd_device *device = user_data->device;
+
+ DBG("set volume");
+
+ media_transport_update_device_volume(device, volume);
+}
+
+static struct bt_vcp_vr_ops vcp_vr_ops = {
+ .set_volume = vr_set_volume,
+};
+
static void vcp_data_add(struct vcp_data *data)
{
DBG("data %p", data);
@@ -94,6 +109,7 @@ static void vcp_data_add(struct vcp_data *data)

bt_vcp_set_debug(data->vcp, vcp_debug, NULL, NULL);

+ bt_vcp_vr_set_ops(data->vcp, &vcp_vr_ops, data);
if (!sessions)
sessions = queue_new();

@@ -178,6 +194,7 @@ static void vcp_attached(struct bt_vcp *vcp, void *user_data)
data->vcp = vcp;

vcp_data_add(data);
+
}

static int vcp_probe(struct btd_service *service)
--
2.25.1

2022-10-07 06:35:04

by Sathish Narasimman

[permalink] [raw]
Subject: [PATCH BlueZ v2 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-07 07:46:46

by bluez.test.bot

[permalink] [raw]
Subject: RE: [BlueZ,v2,1/3] audio/transport: Add volume callback to BAP 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=683646

---Test result---

Test Summary:
CheckPatch PASS 2.41 seconds
GitLint PASS 1.40 seconds
Prep - Setup ELL PASS 31.92 seconds
Build - Prep PASS 0.66 seconds
Build - Configure PASS 10.33 seconds
Build - Make PASS 963.09 seconds
Make Check PASS 13.13 seconds
Make Check w/Valgrind PASS 347.55 seconds
Make Distcheck PASS 292.36 seconds
Build w/ext ELL - Configure PASS 10.51 seconds
Build w/ext ELL - Make PASS 101.36 seconds
Incremental Build w/ patches PASS 359.03 seconds
Scan Build PASS 624.27 seconds



---
Regards,
Linux Bluetooth

2022-10-09 08:41:49

by Sathish Narasimman

[permalink] [raw]
Subject: Re: [BlueZ,v2,1/3] audio/transport: Add volume callback to BAP transport

Hi

On Fri, Oct 7, 2022 at 1:26 PM <[email protected]> wrote:
>
> 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=683646
>
> ---Test result---
>
> Test Summary:
> CheckPatch PASS 2.41 seconds
> GitLint PASS 1.40 seconds
> Prep - Setup ELL PASS 31.92 seconds
> Build - Prep PASS 0.66 seconds
> Build - Configure PASS 10.33 seconds
> Build - Make PASS 963.09 seconds
> Make Check PASS 13.13 seconds
> Make Check w/Valgrind PASS 347.55 seconds
> Make Distcheck PASS 292.36 seconds
> Build w/ext ELL - Configure PASS 10.51 seconds
> Build w/ext ELL - Make PASS 101.36 seconds
> Incremental Build w/ patches PASS 359.03 seconds
> Scan Build PASS 624.27 seconds
>
>
>

Please help to review the changes


> ---
> Regards,
> Linux Bluetooth
>

Regards
Sathish N

2022-10-10 20:01:11

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH BlueZ v2 1/3] audio/transport: Add volume callback to BAP transport

Hi Sathish,

On Thu, Oct 6, 2022 at 11:26 PM Sathish Narasimman
<[email protected]> wrote:
>
> Initialize set_volume and get_volume to BAP transport and update the
> volume when media_transport_update_device_volume is called.
> ---
> profiles/audio/transport.c | 98 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 98 insertions(+)
>
> diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
> index 41339da51e17..46b936c965bf 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_vol)(struct media_transport *transport,
> + int8_t volume);
> + int8_t (*get_vol)(struct media_transport *transport);

Lets have volume in the function name instead of just vol above.

> GDestroyNotify destroy;
> void *data;
> };
> @@ -717,6 +721,7 @@ static gboolean volume_exists(const GDBusPropertyTable *property, void *data)
> return a2dp->volume >= 0;
> }
>
> +
> static gboolean get_volume(const GDBusPropertyTable *property,
> DBusMessageIter *iter, void *data)
> {
> @@ -769,6 +774,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 +1027,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 },
> @@ -1387,6 +1445,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 +1486,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 +1497,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_vol = set_volume_bap;
> + transport->get_vol = get_volume_bap;

Im not seeing any initialization for A2DP or that doesn't need
dedicated callbacks?

> transport->destroy = free_bap;
>
> return 0;
> @@ -1537,6 +1623,11 @@ 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;
> +
> + /* Get BAP transport volume */
> + if (transport->get_vol)
> + return transport->get_vol(transport);
> +
> if (transport->device != dev)
> continue;
>
> @@ -1560,6 +1651,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;
> +
> + /* Set BAP transport volume */
> + if (transport->set_vol) {
> + transport->set_vol(transport, volume);
> + return;
> + }
> +
> if (transport->device != dev)
> continue;
>
> --
> 2.25.1
>


--
Luiz Augusto von Dentz

2022-10-11 04:07:25

by Sathish Narasimman

[permalink] [raw]
Subject: Re: [PATCH BlueZ v2 1/3] audio/transport: Add volume callback to BAP transport

Hi Luiz

On Tue, Oct 11, 2022 at 1:45 AM Luiz Augusto von Dentz
<[email protected]> wrote:
>
> Hi Sathish,
>
> On Thu, Oct 6, 2022 at 11:26 PM Sathish Narasimman
> <[email protected]> wrote:
> >
> > Initialize set_volume and get_volume to BAP transport and update the
> > volume when media_transport_update_device_volume is called.
> > ---
> > profiles/audio/transport.c | 98 ++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 98 insertions(+)
> >
> > diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
> > index 41339da51e17..46b936c965bf 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_vol)(struct media_transport *transport,
> > + int8_t volume);
> > + int8_t (*get_vol)(struct media_transport *transport);
>
> Lets have volume in the function name instead of just vol above.
For the present indentation if we use set_volume it exceeds 80 spaces.
Not sure if we can split the like this
"struct media_transport
*transport"
in 2 lines. If the above is allowed,I will make the changes and submit.

>
> > GDestroyNotify destroy;
> > void *data;
> > };
> > @@ -717,6 +721,7 @@ static gboolean volume_exists(const GDBusPropertyTable *property, void *data)
> > return a2dp->volume >= 0;
> > }
> >
> > +
> > static gboolean get_volume(const GDBusPropertyTable *property,
> > DBusMessageIter *iter, void *data)
> > {
> > @@ -769,6 +774,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 +1027,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 },
> > @@ -1387,6 +1445,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 +1486,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 +1497,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_vol = set_volume_bap;
> > + transport->get_vol = get_volume_bap;
>
> Im not seeing any initialization for A2DP or that doesn't need
> dedicated callbacks?
yes, I have missed it just to keep bap changes. will update in v3
>
> > transport->destroy = free_bap;
> >
> > return 0;
> > @@ -1537,6 +1623,11 @@ 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;
> > +
> > + /* Get BAP transport volume */
> > + if (transport->get_vol)
> > + return transport->get_vol(transport);
> > +
> > if (transport->device != dev)
> > continue;
> >
> > @@ -1560,6 +1651,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;
> > +
> > + /* Set BAP transport volume */
> > + if (transport->set_vol) {
> > + transport->set_vol(transport, volume);
> > + return;
> > + }
> > +
> > if (transport->device != dev)
> > continue;
> >
> > --
> > 2.25.1
> >
>
>
> --
> Luiz Augusto von Dentz

Sathish N