bluez5: backend-ofono: set media_codec on created transports

Set media_codec on created transports.

Also avoid using the HFP codec id in spa_bt_transport::codec
This commit is contained in:
Pauli Virtanen 2025-06-07 20:53:22 +03:00 committed by Wim Taymans
parent 13256e9083
commit 61b0ea4589

View file

@ -23,6 +23,7 @@
#include <spa-private/dbus-helpers.h> #include <spa-private/dbus-helpers.h>
#include "defs.h" #include "defs.h"
#include "media-codecs.h"
#define INITIAL_INTERVAL_NSEC (500 * SPA_NSEC_PER_MSEC) #define INITIAL_INTERVAL_NSEC (500 * SPA_NSEC_PER_MSEC)
#define ACTION_INTERVAL_NSEC (3000 * SPA_NSEC_PER_MSEC) #define ACTION_INTERVAL_NSEC (3000 * SPA_NSEC_PER_MSEC)
@ -53,6 +54,7 @@ struct impl {
struct transport_data { struct transport_data {
struct spa_source sco; struct spa_source sco;
unsigned int codec_id;
unsigned int broken:1; unsigned int broken:1;
unsigned int activated:1; unsigned int activated:1;
}; };
@ -112,17 +114,26 @@ static struct spa_bt_transport *_transport_create(struct impl *backend,
const char *path, const char *path,
struct spa_bt_device *device, struct spa_bt_device *device,
enum spa_bt_profile profile, enum spa_bt_profile profile,
int codec, int codec_id,
struct spa_callbacks *impl) struct spa_callbacks *impl)
{ {
struct spa_bt_transport *t = NULL; struct spa_bt_transport *t = NULL;
char *t_path = strdup(path); const struct media_codec *codec;
struct transport_data *td;
char *t_path;
codec = spa_bt_get_hfp_codec(backend->monitor, codec_id);
if (!codec) {
spa_log_warn(backend->log, "can't create transport: no HFP codec %d", codec_id);
return NULL;
}
t_path = strdup(path);
t = spa_bt_transport_create(backend->monitor, t_path, sizeof(struct transport_data)); t = spa_bt_transport_create(backend->monitor, t_path, sizeof(struct transport_data));
if (t == NULL) { if (t == NULL) {
spa_log_warn(backend->log, "can't create transport: %m"); spa_log_warn(backend->log, "can't create transport: %m");
free(t_path); free(t_path);
goto finish; return NULL;
} }
spa_bt_transport_set_implementation(t, impl, t); spa_bt_transport_set_implementation(t, impl, t);
@ -130,11 +141,14 @@ static struct spa_bt_transport *_transport_create(struct impl *backend,
spa_list_append(&t->device->transport_list, &t->device_link); spa_list_append(&t->device->transport_list, &t->device_link);
t->backend = &backend->this; t->backend = &backend->this;
t->profile = profile; t->profile = profile;
t->codec = codec; t->media_codec = codec;
t->codec = codec_id;
t->n_channels = 1; t->n_channels = 1;
t->channels[0] = SPA_AUDIO_CHANNEL_MONO; t->channels[0] = SPA_AUDIO_CHANNEL_MONO;
finish: td = t->user_data;
td->codec_id = codec_id;
return t; return t;
} }
@ -186,7 +200,7 @@ static int ofono_audio_acquire(void *data, bool optional)
struct spa_bt_transport *transport = data; struct spa_bt_transport *transport = data;
struct transport_data *td = transport->user_data; struct transport_data *td = transport->user_data;
struct impl *backend = SPA_CONTAINER_OF(transport->backend, struct impl, this); struct impl *backend = SPA_CONTAINER_OF(transport->backend, struct impl, this);
uint8_t codec; uint8_t codec_id;
int ret = 0; int ret = 0;
if (transport->fd >= 0) if (transport->fd >= 0)
@ -198,17 +212,17 @@ static int ofono_audio_acquire(void *data, bool optional)
spa_bt_device_update_last_bluez_action_time(transport->device); spa_bt_device_update_last_bluez_action_time(transport->device);
ret = _audio_acquire(backend, transport->path, &codec); ret = _audio_acquire(backend, transport->path, &codec_id);
if (ret < 0) if (ret < 0)
goto finish; goto finish;
transport->fd = ret; transport->fd = ret;
if (transport->codec != codec) { if (transport->media_codec->codec_id != codec_id) {
struct timespec ts; struct timespec ts;
spa_log_info(backend->log, "transport %p: acquired codec (%d) differs from transport one (%d)", spa_log_info(backend->log, "transport %p: acquired codec (%d) differs from transport one (%d)",
transport, codec, transport->codec); transport, codec_id, transport->media_codec->codec_id);
/* shutdown to make sure connection is dropped immediately */ /* shutdown to make sure connection is dropped immediately */
shutdown(transport->fd, SHUT_RDWR); shutdown(transport->fd, SHUT_RDWR);
@ -216,7 +230,7 @@ static int ofono_audio_acquire(void *data, bool optional)
transport->fd = -1; transport->fd = -1;
/* schedule immediate profile update, from main loop */ /* schedule immediate profile update, from main loop */
transport->codec = codec; td->codec_id = codec_id;
td->broken = true; td->broken = true;
ts.tv_sec = 0; ts.tv_sec = 0;
ts.tv_nsec = 1; ts.tv_nsec = 1;
@ -229,8 +243,8 @@ static int ofono_audio_acquire(void *data, bool optional)
td->broken = false; td->broken = false;
spa_log_debug(backend->log, "transport %p: Acquire %s, fd %d codec %d", transport, spa_log_debug(backend->log, "transport %p: Acquire %s, fd %d codec %s", transport,
transport->path, transport->fd, transport->codec); transport->path, transport->fd, transport->media_codec->description);
ofono_transport_get_mtu(backend, transport); ofono_transport_get_mtu(backend, transport);
ret = 0; ret = 0;
@ -332,7 +346,7 @@ static bool activate_transport(struct spa_bt_transport *t, const void *data)
struct spa_bt_transport *t_copy; struct spa_bt_transport *t_copy;
t_copy = _transport_create(backend, t->path, t->device, t_copy = _transport_create(backend, t->path, t->device,
t->profile, t->codec, (struct spa_callbacks *)&ofono_transport_impl); t->profile, td->codec_id, (struct spa_callbacks *)&ofono_transport_impl);
spa_bt_transport_free(t); spa_bt_transport_free(t);
if (t_copy) if (t_copy)
@ -364,7 +378,7 @@ static DBusHandlerResult ofono_audio_card_found(struct impl *backend, char *path
struct spa_bt_transport *t; struct spa_bt_transport *t;
struct transport_data *td; struct transport_data *td;
enum spa_bt_profile profile = SPA_BT_PROFILE_HFP_AG; enum spa_bt_profile profile = SPA_BT_PROFILE_HFP_AG;
uint8_t codec = backend->msbc_supported ? uint8_t codec_id = backend->msbc_supported ?
HFP_AUDIO_CODEC_MSBC : HFP_AUDIO_CODEC_CVSD; HFP_AUDIO_CODEC_MSBC : HFP_AUDIO_CODEC_CVSD;
spa_assert(backend); spa_assert(backend);
@ -417,7 +431,7 @@ static DBusHandlerResult ofono_audio_card_found(struct impl *backend, char *path
} }
spa_bt_device_add_profile(d, profile); spa_bt_device_add_profile(d, profile);
t = _transport_create(backend, path, d, profile, codec, (struct spa_callbacks *)&ofono_transport_impl); t = _transport_create(backend, path, d, profile, codec_id, (struct spa_callbacks *)&ofono_transport_impl);
if (t == NULL) { if (t == NULL) {
spa_log_error(backend->log, "failed to create transport: %s", spa_strerror(-errno)); spa_log_error(backend->log, "failed to create transport: %s", spa_strerror(-errno));
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@ -444,7 +458,7 @@ static DBusHandlerResult ofono_audio_card_found(struct impl *backend, char *path
spa_bt_device_connect_profile(t->device, t->profile); spa_bt_device_connect_profile(t->device, t->profile);
} }
spa_log_debug(backend->log, "Transport %s available, codec %d", t->path, t->codec); spa_log_debug(backend->log, "Transport %s available, codec %s", t->path, t->media_codec->description);
return DBUS_HANDLER_RESULT_HANDLED; return DBUS_HANDLER_RESULT_HANDLED;
} }
@ -513,7 +527,7 @@ static DBusHandlerResult ofono_new_audio_connection(DBusConnection *conn, DBusMe
struct impl *backend = userdata; struct impl *backend = userdata;
const char *path; const char *path;
int fd; int fd;
uint8_t codec; uint8_t codec_id;
struct spa_bt_transport *t; struct spa_bt_transport *t;
struct transport_data *td; struct transport_data *td;
spa_autoptr(DBusMessage) r = NULL; spa_autoptr(DBusMessage) r = NULL;
@ -521,7 +535,7 @@ static DBusHandlerResult ofono_new_audio_connection(DBusConnection *conn, DBusMe
if (dbus_message_get_args(m, NULL, if (dbus_message_get_args(m, NULL,
DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_UNIX_FD, &fd,
DBUS_TYPE_BYTE, &codec, DBUS_TYPE_BYTE, &codec_id,
DBUS_TYPE_INVALID) == FALSE) { DBUS_TYPE_INVALID) == FALSE) {
r = dbus_message_new_error(m, OFONO_ERROR_INVALID_ARGUMENTS, "Invalid arguments in method call"); r = dbus_message_new_error(m, OFONO_ERROR_INVALID_ARGUMENTS, "Invalid arguments in method call");
goto fail; goto fail;
@ -530,6 +544,15 @@ static DBusHandlerResult ofono_new_audio_connection(DBusConnection *conn, DBusMe
t = spa_bt_transport_find(backend->monitor, path); t = spa_bt_transport_find(backend->monitor, path);
if (t && (t->profile & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY)) { if (t && (t->profile & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY)) {
int err; int err;
const struct media_codec *codec;
codec = spa_bt_get_hfp_codec(backend->monitor, codec_id);
if (!codec) {
spa_log_error(backend->log, "transport %p: Couldn't find HFP codec %d", t, codec_id);
shutdown(fd, SHUT_RDWR);
close(fd);
goto fail;
}
err = enable_sco_socket(fd); err = enable_sco_socket(fd);
if (err) { if (err) {
@ -541,10 +564,11 @@ static DBusHandlerResult ofono_new_audio_connection(DBusConnection *conn, DBusMe
} }
t->fd = fd; t->fd = fd;
t->codec = codec; t->codec = codec_id;
t->media_codec = codec;
spa_log_debug(backend->log, "transport %p: NewConnection %s, fd %d codec %d", spa_log_debug(backend->log, "transport %p: NewConnection %s, fd %d codec %s",
t, t->path, t->fd, t->codec); t, t->path, t->fd, t->media_codec->description);
td = t->user_data; td = t->user_data;
td->sco.func = sco_event; td->sco.func = sco_event;