bluez5: lc3: handle multiple PACs in capabilities

BlueZ may send multiple PACs in the capabilities delimited by zero LTV.
Handle this case by selecting the "best" one.

The configuration size may also for BAP generally be different from PAC
size.
This commit is contained in:
Pauli Virtanen 2023-01-16 22:54:27 +02:00
parent 37a5dca31e
commit a372c89544
3 changed files with 124 additions and 48 deletions

View file

@ -628,6 +628,7 @@ static DBusHandlerResult endpoint_select_properties(DBusConnection *conn, DBusMe
uint8_t caps[A2DP_MAX_CAPS_SIZE];
uint8_t config[A2DP_MAX_CAPS_SIZE];
int caps_size = 0;
int conf_size;
DBusMessageIter dict;
struct bap_endpoint_qos endpoint_qos;
@ -688,6 +689,10 @@ static DBusHandlerResult endpoint_select_properties(DBusConnection *conn, DBusMe
}
dbus_message_iter_get_fixed_array(&array, &buf, &caps_size);
if (caps_size > (int)sizeof(caps)) {
spa_log_error(monitor->log, "%s size:%d too large", key, (int)caps_size);
goto error_invalid;
}
memcpy(caps, buf, caps_size);
spa_log_info(monitor->log, "%p: %s %s size:%d", monitor, path, key, caps_size);
@ -764,15 +769,14 @@ static DBusHandlerResult endpoint_select_properties(DBusConnection *conn, DBusMe
/* TODO: determine which device the SelectConfiguration() call is associated
* with; it's known here based on the remote endpoint.
*/
res = codec->select_config(codec, 0, caps, caps_size, &monitor->default_audio_info, NULL, config);
if (res < 0 || res != caps_size) {
conf_size = codec->select_config(codec, 0, caps, caps_size, &monitor->default_audio_info, NULL, config);
if (conf_size < 0) {
spa_log_error(monitor->log, "can't select config: %d (%s)",
res, spa_strerror(res));
conf_size, spa_strerror(conf_size));
goto error_invalid;
}
spa_log_info(monitor->log, "%p: selected conf %d", monitor, caps_size);
spa_log_hexdump(monitor->log, SPA_LOG_LEVEL_DEBUG, ' ', (uint8_t *)config, (size_t)caps_size);
spa_log_info(monitor->log, "%p: selected conf %d", monitor, conf_size);
spa_log_hexdump(monitor->log, SPA_LOG_LEVEL_DEBUG, ' ', (uint8_t *)config, (size_t)conf_size);
if ((r = dbus_message_new_method_return(m)) == NULL)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
@ -784,7 +788,7 @@ static DBusHandlerResult endpoint_select_properties(DBusConnection *conn, DBusMe
DBUS_TYPE_VARIANT_AS_STRING
DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
&dict);
append_basic_array_variant_dict_entry(&dict, "Capabilities", "ay", "y", DBUS_TYPE_BYTE, &config, caps_size);
append_basic_array_variant_dict_entry(&dict, "Capabilities", "ay", "y", DBUS_TYPE_BYTE, &config, conf_size);
if (codec->get_qos) {
struct bap_codec_qos qos;
@ -793,7 +797,7 @@ static DBusHandlerResult endpoint_select_properties(DBusConnection *conn, DBusMe
spa_zero(qos);
res = codec->get_qos(codec, config, caps_size, &endpoint_qos, &qos);
res = codec->get_qos(codec, config, conf_size, &endpoint_qos, &qos);
if (res < 0) {
spa_log_error(monitor->log, "can't select QOS config: %d (%s)",
res, spa_strerror(res));