@@ -48,6 +48,7 @@
#include "src/dbus-common.h"
#include "src/shared/timeout.h"
#include "src/shared/util.h"
+#include "src/btd.h"
#include "avctp.h"
#include "avrcp.h"
@@ -4670,9 +4671,18 @@ int avrcp_set_volume(struct btd_device *dev, int8_t volume, bool notify)
&volume);
}
- if (!session->controller && !avrcp_event_registered(session,
- AVRCP_EVENT_VOLUME_CHANGED))
- return -ENOTSUP;
+ if (btd_opts.avrcp.volume_without_target) {
+ /* If there is no target profile (we didn't create a controller for it),
+ * allow the call to pass through if the remote controller registered
+ * for a volume changed event.
+ */
+ if (!session->controller && !avrcp_event_registered(session,
+ AVRCP_EVENT_VOLUME_CHANGED))
+ return -ENOTSUP;
+ } else {
+ if (!session->controller || session->controller->version < 0x0104)
+ return -ENOTSUP;
+ }
memset(buf, 0, sizeof(buf));
@@ -104,6 +104,10 @@ struct btd_avdtp_opts {
uint8_t stream_mode;
};
+struct btd_avrcp_opts {
+ bool volume_without_target;
+};
+
struct btd_advmon_opts {
uint8_t rssi_sampling_period;
};
@@ -145,6 +149,7 @@ struct btd_opts {
enum mps_mode_t mps;
struct btd_avdtp_opts avdtp;
+ struct btd_avrcp_opts avrcp;
uint8_t key_size;
@@ -165,6 +165,11 @@ static const char *avdtp_options[] = {
NULL
};
+static const char *avrcp_options[] = {
+ "VolumeWithoutTarget",
+ NULL
+};
+
static const char *advmon_options[] = {
"RSSISamplingPeriod",
NULL
@@ -181,6 +186,7 @@ static const struct group_table {
{ "GATT", gatt_options },
{ "CSIS", csip_options },
{ "AVDTP", avdtp_options },
+ { "AVRCP", avrcp_options },
{ "AdvMon", advmon_options },
{ }
};
@@ -1140,6 +1146,13 @@ static void parse_avdtp(GKeyFile *config)
parse_avdtp_stream_mode(config);
}
+static void parse_avrcp(GKeyFile *config)
+{
+ parse_config_bool(config, "AVRCP",
+ "VolumeWithoutTarget",
+ &btd_opts.avrcp.volume_without_target);
+}
+
static void parse_advmon(GKeyFile *config)
{
parse_config_u8(config, "AdvMon", "RSSISamplingPeriod",
@@ -1163,6 +1176,7 @@ static void parse_config(GKeyFile *config)
parse_gatt(config);
parse_csis(config);
parse_avdtp(config);
+ parse_avrcp(config);
parse_advmon(config);
}
@@ -1205,6 +1219,8 @@ static void init_defaults(void)
btd_opts.avdtp.session_mode = BT_IO_MODE_BASIC;
btd_opts.avdtp.stream_mode = BT_IO_MODE_BASIC;
+ btd_opts.avrcp.volume_without_target = false;
+
btd_opts.advmon.rssi_sampling_period = 0xFF;
btd_opts.csis.encrypt = true;
}
@@ -305,6 +305,12 @@
# streaming: Use L2CAP Streaming Mode
#StreamMode = basic
+[AVRCP]
+# Allow SetAbsoluteVolume calls to a peer device that does not advertise the
+# AVRCP remote control target profile. If it does advertise this profile, the
+# version is ignored.
+#VolumeWithoutTarget = false
+
[Policy]
#
# The ReconnectUUIDs defines the set of remote services that should try