@@ -1779,9 +1779,10 @@ static uint8_t avrcp_handle_set_absolute_volume(struct avrcp *session,
* The controller on the remote end is only allowed to call SetAbsoluteVolume
* on our target if it's at least version 1.4 and a category-2 device.
*/
- if (!session->target || session->target->version < 0x0104 ||
+ if (!session->target ||
+ (btd_opts.avrcp.volume_version && session->target->version < 0x0104) ||
(btd_opts.avrcp.volume_category && !(session->target->features & AVRCP_FEATURE_CATEGORY_2))) {
- error("Remote SetAbsoluteVolume rejected from non-category-2 peer");
+ error("Remote SetAbsoluteVolume rejected from non-category-2 or non-AVRCP-1.4 peer");
goto err;
}
@@ -4262,13 +4263,15 @@ static void target_init(struct avrcp *session)
(1 << AVRCP_EVENT_TRACK_REACHED_END) |
(1 << AVRCP_EVENT_SETTINGS_CHANGED);
- if (target->version < 0x0104)
- return;
-
- if (!btd_opts.avrcp.volume_category || target->features & AVRCP_FEATURE_CATEGORY_2)
+ /* Remote device supports receiving volume notifications */
+ if ((!btd_opts.avrcp.volume_version || target->version >= 0x0104) &&
+ (!btd_opts.avrcp.volume_category || target->features & AVRCP_FEATURE_CATEGORY_2))
session->supported_events |=
(1 << AVRCP_EVENT_VOLUME_CHANGED);
+ if (target->version < 0x0104)
+ return;
+
session->supported_events |=
(1 << AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED) |
(1 << AVRCP_EVENT_AVAILABLE_PLAYERS_CHANGED);
@@ -4688,9 +4691,10 @@ int avrcp_set_volume(struct btd_device *dev, int8_t volume, bool notify)
return -ENOTCONN;
if (notify) {
- if (!session->target || session->target->version < 0x0104 ||
+ if (!session->target ||
+ (btd_opts.avrcp.volume_version && session->target->version < 0x0104) ||
(btd_opts.avrcp.volume_category && !(session->target->features & AVRCP_FEATURE_CATEGORY_2))) {
- error("Can't send EVENT_VOLUME_CHANGED to non-category-2 peer");
+ error("Can't send EVENT_VOLUME_CHANGED to non-category-2 or non-AVRCP-1.4 peer");
return -ENOTSUP;
}
return avrcp_event(session, AVRCP_EVENT_VOLUME_CHANGED,
@@ -107,6 +107,7 @@ struct btd_avdtp_opts {
struct btd_avrcp_opts {
bool volume_without_target;
bool volume_category;
+ bool volume_version;
};
struct btd_advmon_opts {
@@ -168,6 +168,7 @@ static const char *avdtp_options[] = {
static const char *avrcp_options[] = {
"VolumeWithoutTarget",
"VolumeCategory",
+ "VolumeVersion",
NULL
};
@@ -1155,6 +1156,9 @@ static void parse_avrcp(GKeyFile *config)
parse_config_bool(config, "AVRCP",
"VolumeCategory",
&btd_opts.avrcp.volume_category);
+ parse_config_bool(config, "AVRCP",
+ "VolumeVersion",
+ &btd_opts.avrcp.volume_version);
}
static void parse_advmon(GKeyFile *config)
@@ -1225,6 +1229,7 @@ static void init_defaults(void)
btd_opts.avrcp.volume_without_target = false;
btd_opts.avrcp.volume_category = true;
+ btd_opts.avrcp.volume_version = false;
btd_opts.advmon.rssi_sampling_period = 0xFF;
btd_opts.csis.encrypt = true;
@@ -316,6 +316,15 @@
# notifications.
#VolumeCategory = true
+# Require peer AVRCP controllers to have at least version 1.4 before
+# accessing category-2 (absolute volume) features (depending on the value
+# of VolumeCategory above). It is common for Android-powered devices to not
+# signal the desired minimum version of 1.4 while still supporting absolute
+# volume based on the feature category bit, as mentioned in this comment:
+# https://android.googlesource.com/platform/system/bt/+/android-12.0.0_r1/bta/
+# av/bta_av_main.cc#621
+#VolumeVersion = false
+
[Policy]
#
# The ReconnectUUIDs defines the set of remote services that should try