mirror of
https://gitlab.freedesktop.org/pipewire/pipewire
synced 2024-10-14 11:53:16 +00:00
spa: bluez: use some more spa_auto*
This commit is contained in:
parent
ca85872e83
commit
4083502e03
|
@ -538,7 +538,6 @@ static DBusHandlerResult hsphfpd_new_audio_connection(DBusConnection *conn, DBus
|
|||
struct impl *backend = userdata;
|
||||
DBusMessageIter arg_i;
|
||||
const char *transport_path;
|
||||
int fd;
|
||||
const char *sender;
|
||||
const char *endpoint_path = NULL;
|
||||
const char *air_codec = NULL;
|
||||
|
@ -552,6 +551,7 @@ static DBusHandlerResult hsphfpd_new_audio_connection(DBusConnection *conn, DBus
|
|||
struct spa_bt_transport *transport;
|
||||
struct hsphfpd_transport_data *transport_data;
|
||||
spa_autoptr(DBusMessage) r = NULL;
|
||||
spa_autoclose int fd = -1;
|
||||
|
||||
if (!check_signature(m, "oha{sv}")) {
|
||||
r = dbus_message_new_error(m, DBUS_ERROR_INVALID_ARGS, "Invalid signature in method call");
|
||||
|
@ -569,7 +569,6 @@ static DBusHandlerResult hsphfpd_new_audio_connection(DBusConnection *conn, DBus
|
|||
|
||||
sender = dbus_message_get_sender(m);
|
||||
if (!spa_streq(sender, backend->hsphfpd_service_id)) {
|
||||
close(fd);
|
||||
spa_log_error(backend->log, "Sender '%s' is not authorized", sender);
|
||||
r = dbus_message_new_error_printf(m, HSPHFPD_ERROR_REJECTED, "Sender '%s' is not authorized", sender);
|
||||
goto fail;
|
||||
|
@ -592,28 +591,24 @@ static DBusHandlerResult hsphfpd_new_audio_connection(DBusConnection *conn, DBus
|
|||
&mtu);
|
||||
|
||||
if (!endpoint_path) {
|
||||
close(fd);
|
||||
spa_log_error(backend->log, "Endpoint property was not specified");
|
||||
r = dbus_message_new_error(m, HSPHFPD_ERROR_REJECTED, "Endpoint property was not specified");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!air_codec) {
|
||||
close(fd);
|
||||
spa_log_error(backend->log, "AirCodec property was not specified");
|
||||
r = dbus_message_new_error(m, HSPHFPD_ERROR_REJECTED, "AirCodec property was not specified");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!rx_volume_control) {
|
||||
close(fd);
|
||||
spa_log_error(backend->log, "RxVolumeControl property was not specified");
|
||||
r = dbus_message_new_error(m, HSPHFPD_ERROR_REJECTED, "RxVolumeControl property was not specified");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!tx_volume_control) {
|
||||
close(fd);
|
||||
spa_log_error(backend->log, "TxVolumeControl property was not specified");
|
||||
r = dbus_message_new_error(m, HSPHFPD_ERROR_REJECTED, "TxVolumeControl property was not specified");
|
||||
goto fail;
|
||||
|
@ -621,7 +616,6 @@ static DBusHandlerResult hsphfpd_new_audio_connection(DBusConnection *conn, DBus
|
|||
|
||||
if (rx_volume_control != HSPHFPD_VOLUME_CONTROL_NONE) {
|
||||
if (rx_volume_gain == (uint16_t)-1) {
|
||||
close(fd);
|
||||
spa_log_error(backend->log, "RxVolumeGain property was not specified, but VolumeControl is not none");
|
||||
r = dbus_message_new_error(m, HSPHFPD_ERROR_REJECTED, "RxVolumeGain property was not specified, but VolumeControl is not none");
|
||||
goto fail;
|
||||
|
@ -632,7 +626,6 @@ static DBusHandlerResult hsphfpd_new_audio_connection(DBusConnection *conn, DBus
|
|||
|
||||
if (tx_volume_control != HSPHFPD_VOLUME_CONTROL_NONE) {
|
||||
if (tx_volume_gain == (uint16_t)-1) {
|
||||
close(fd);
|
||||
spa_log_error(backend->log, "TxVolumeGain property was not specified, but VolumeControl is not none");
|
||||
r = dbus_message_new_error(m, HSPHFPD_ERROR_REJECTED, "TxVolumeGain property was not specified, but VolumeControl is not none");
|
||||
goto fail;
|
||||
|
@ -642,7 +635,6 @@ static DBusHandlerResult hsphfpd_new_audio_connection(DBusConnection *conn, DBus
|
|||
}
|
||||
|
||||
if (!mtu) {
|
||||
close(fd);
|
||||
spa_log_error(backend->log, "MTU property was not specified");
|
||||
r = dbus_message_new_error(m, HSPHFPD_ERROR_REJECTED, "MTU property was not specified");
|
||||
goto fail;
|
||||
|
@ -650,14 +642,12 @@ static DBusHandlerResult hsphfpd_new_audio_connection(DBusConnection *conn, DBus
|
|||
|
||||
endpoint = endpoint_find(backend, endpoint_path);
|
||||
if (!endpoint) {
|
||||
close(fd);
|
||||
spa_log_error(backend->log, "Endpoint %s does not exist", endpoint_path);
|
||||
r = dbus_message_new_error_printf(m, HSPHFPD_ERROR_REJECTED, "Endpoint %s does not exist", endpoint_path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!endpoint->valid) {
|
||||
close(fd);
|
||||
spa_log_error(backend->log, "Endpoint %s is not valid", endpoint_path);
|
||||
r = dbus_message_new_error_printf(m, HSPHFPD_ERROR_REJECTED, "Endpoint %s is not valid", endpoint_path);
|
||||
goto fail;
|
||||
|
@ -665,7 +655,6 @@ static DBusHandlerResult hsphfpd_new_audio_connection(DBusConnection *conn, DBus
|
|||
|
||||
transport = spa_bt_transport_find(backend->monitor, endpoint_path);
|
||||
if (!transport) {
|
||||
close(fd);
|
||||
spa_log_error(backend->log, "Endpoint %s is not connected", endpoint_path);
|
||||
r = dbus_message_new_error_printf(m, HSPHFPD_ERROR_REJECTED, "Endpoint %s is not connected", endpoint_path);
|
||||
goto fail;
|
||||
|
@ -675,7 +664,6 @@ static DBusHandlerResult hsphfpd_new_audio_connection(DBusConnection *conn, DBus
|
|||
spa_log_warn(backend->log, "Expecting codec to be %d, got %d", transport->codec, codec);
|
||||
|
||||
if (transport->fd >= 0) {
|
||||
close(fd);
|
||||
spa_log_error(backend->log, "Endpoint %s has already active transport", endpoint_path);
|
||||
r = dbus_message_new_error_printf(m, HSPHFPD_ERROR_REJECTED, "Endpoint %s has already active transport", endpoint_path);
|
||||
goto fail;
|
||||
|
@ -698,7 +686,7 @@ static DBusHandlerResult hsphfpd_new_audio_connection(DBusConnection *conn, DBus
|
|||
transport->read_mtu = mtu;
|
||||
transport->write_mtu = mtu;
|
||||
|
||||
transport->fd = fd;
|
||||
transport->fd = spa_steal_fd(fd);
|
||||
|
||||
if ((r = dbus_message_new_method_return(m)) == NULL)
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
|
|
|
@ -1383,12 +1383,11 @@ static int sco_create_socket(struct impl *backend, struct spa_bt_adapter *adapte
|
|||
struct sockaddr_sco addr;
|
||||
socklen_t len;
|
||||
bdaddr_t src;
|
||||
int sock = -1;
|
||||
|
||||
sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET | SOCK_NONBLOCK, BTPROTO_SCO);
|
||||
spa_autoclose int sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET | SOCK_NONBLOCK, BTPROTO_SCO);
|
||||
if (sock < 0) {
|
||||
spa_log_error(backend->log, "socket(SEQPACKET, SCO) %s", strerror(errno));
|
||||
goto fail;
|
||||
return -1;
|
||||
}
|
||||
|
||||
str2ba(adapter->address, &src);
|
||||
|
@ -1400,7 +1399,7 @@ static int sco_create_socket(struct impl *backend, struct spa_bt_adapter *adapte
|
|||
|
||||
if (bind(sock, (struct sockaddr *) &addr, len) < 0) {
|
||||
spa_log_error(backend->log, "bind(): %s", strerror(errno));
|
||||
goto fail;
|
||||
return -1;
|
||||
}
|
||||
|
||||
spa_log_debug(backend->log, "msbc=%d", (int)msbc);
|
||||
|
@ -1411,16 +1410,11 @@ static int sco_create_socket(struct impl *backend, struct spa_bt_adapter *adapte
|
|||
voice_config.setting = BT_VOICE_TRANSPARENT;
|
||||
if (setsockopt(sock, SOL_BLUETOOTH, BT_VOICE, &voice_config, sizeof(voice_config)) < 0) {
|
||||
spa_log_error(backend->log, "setsockopt(): %s", strerror(errno));
|
||||
goto fail;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return sock;
|
||||
|
||||
fail:
|
||||
if (sock >= 0)
|
||||
close(sock);
|
||||
return -1;
|
||||
return spa_steal_fd(sock);
|
||||
}
|
||||
|
||||
static int sco_do_connect(struct spa_bt_transport *t)
|
||||
|
@ -1429,11 +1423,7 @@ static int sco_do_connect(struct spa_bt_transport *t)
|
|||
struct spa_bt_device *d = t->device;
|
||||
struct transport_data *td = t->user_data;
|
||||
struct sockaddr_sco addr;
|
||||
socklen_t len;
|
||||
int err;
|
||||
int sock;
|
||||
bdaddr_t dst;
|
||||
int retry = 2;
|
||||
|
||||
spa_log_debug(backend->log, "transport %p: enter sco_do_connect, codec=%u",
|
||||
t, t->codec);
|
||||
|
@ -1443,52 +1433,45 @@ static int sco_do_connect(struct spa_bt_transport *t)
|
|||
if (d->adapter == NULL)
|
||||
return -EIO;
|
||||
|
||||
str2ba(d->address, &dst);
|
||||
|
||||
again:
|
||||
sock = sco_create_socket(backend, d->adapter, (t->codec == HFP_AUDIO_CODEC_MSBC));
|
||||
if (sock < 0)
|
||||
return -1;
|
||||
|
||||
len = sizeof(addr);
|
||||
memset(&addr, 0, len);
|
||||
spa_zero(addr);
|
||||
addr.sco_family = AF_BLUETOOTH;
|
||||
bacpy(&addr.sco_bdaddr, &dst);
|
||||
str2ba(d->address, &addr.sco_bdaddr);
|
||||
|
||||
spa_log_debug(backend->log, "transport %p: doing connect", t);
|
||||
err = connect(sock, (struct sockaddr *) &addr, len);
|
||||
if (err < 0 && errno == ECONNABORTED && retry-- > 0) {
|
||||
spa_log_warn(backend->log, "connect(): %s. Remaining retry:%d",
|
||||
strerror(errno), retry);
|
||||
close(sock);
|
||||
goto again;
|
||||
} else if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {
|
||||
spa_log_error(backend->log, "connect(): %s", strerror(errno));
|
||||
for (int retry = 2;;) {
|
||||
spa_autoclose int sock = sco_create_socket(backend, d->adapter, (t->codec == HFP_AUDIO_CODEC_MSBC));
|
||||
if (sock < 0)
|
||||
return -1;
|
||||
|
||||
spa_log_debug(backend->log, "transport %p: doing connect", t);
|
||||
err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
|
||||
if (err < 0 && errno == ECONNABORTED && retry-- > 0) {
|
||||
spa_log_warn(backend->log, "connect(): %s. Remaining retry:%d",
|
||||
strerror(errno), retry);
|
||||
continue;
|
||||
} else if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {
|
||||
spa_log_error(backend->log, "connect(): %s", strerror(errno));
|
||||
#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE
|
||||
if (errno == EOPNOTSUPP && t->codec == HFP_AUDIO_CODEC_MSBC &&
|
||||
td->rfcomm->msbc_supported_by_hfp) {
|
||||
/* Adapter doesn't support msbc. Renegotiate. */
|
||||
d->adapter->msbc_probed = true;
|
||||
d->adapter->has_msbc = false;
|
||||
td->rfcomm->msbc_supported_by_hfp = false;
|
||||
if (t->profile == SPA_BT_PROFILE_HFP_HF) {
|
||||
td->rfcomm->hfp_ag_switching_codec = true;
|
||||
rfcomm_send_reply(td->rfcomm, "+BCS: 1");
|
||||
} else if (t->profile == SPA_BT_PROFILE_HFP_AG) {
|
||||
rfcomm_send_cmd(td->rfcomm, "AT+BAC=1");
|
||||
if (errno == EOPNOTSUPP && t->codec == HFP_AUDIO_CODEC_MSBC &&
|
||||
td->rfcomm->msbc_supported_by_hfp) {
|
||||
/* Adapter doesn't support msbc. Renegotiate. */
|
||||
d->adapter->msbc_probed = true;
|
||||
d->adapter->has_msbc = false;
|
||||
td->rfcomm->msbc_supported_by_hfp = false;
|
||||
if (t->profile == SPA_BT_PROFILE_HFP_HF) {
|
||||
td->rfcomm->hfp_ag_switching_codec = true;
|
||||
rfcomm_send_reply(td->rfcomm, "+BCS: 1");
|
||||
} else if (t->profile == SPA_BT_PROFILE_HFP_AG) {
|
||||
rfcomm_send_cmd(td->rfcomm, "AT+BAC=1");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
goto fail_close;
|
||||
return -1;
|
||||
}
|
||||
|
||||
td->err = -EINPROGRESS;
|
||||
|
||||
return spa_steal_fd(sock);
|
||||
}
|
||||
|
||||
td->err = -EINPROGRESS;
|
||||
|
||||
return sock;
|
||||
|
||||
fail_close:
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int rfcomm_ag_sync_volume(struct rfcomm *rfcomm, bool later);
|
||||
|
@ -1719,25 +1702,24 @@ static void sco_listen_event(struct spa_source *source)
|
|||
struct impl *backend = source->data;
|
||||
struct sockaddr_sco addr;
|
||||
socklen_t addrlen;
|
||||
int sock = -1;
|
||||
char local_address[18], remote_address[18];
|
||||
struct rfcomm *rfcomm;
|
||||
struct spa_bt_transport *t = NULL;
|
||||
|
||||
if (source->rmask & (SPA_IO_HUP | SPA_IO_ERR)) {
|
||||
spa_log_error(backend->log, "error listening SCO connection: %s", strerror(errno));
|
||||
goto fail;
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addrlen = sizeof(addr);
|
||||
|
||||
spa_log_debug(backend->log, "doing accept");
|
||||
sock = accept(source->fd, (struct sockaddr *) &addr, &addrlen);
|
||||
spa_autoclose int sock = accept(source->fd, (struct sockaddr *) &addr, &addrlen);
|
||||
if (sock < 0) {
|
||||
if (errno != EAGAIN)
|
||||
spa_log_error(backend->log, "SCO accept(): %s", strerror(errno));
|
||||
goto fail;
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&addr.sco_bdaddr, remote_address);
|
||||
|
@ -1747,7 +1729,7 @@ static void sco_listen_event(struct spa_source *source)
|
|||
|
||||
if (getsockname(sock, (struct sockaddr *) &addr, &addrlen) < 0) {
|
||||
spa_log_error(backend->log, "SCO getsockname(): %s", strerror(errno));
|
||||
goto fail;
|
||||
return;
|
||||
}
|
||||
|
||||
ba2str(&addr.sco_bdaddr, local_address);
|
||||
|
@ -1763,19 +1745,19 @@ static void sco_listen_event(struct spa_source *source)
|
|||
if (!t) {
|
||||
spa_log_debug(backend->log, "No transport for adapter %s and remote %s",
|
||||
local_address, remote_address);
|
||||
goto fail;
|
||||
return;
|
||||
}
|
||||
|
||||
/* The Synchronous Connection shall always be established by the AG, i.e. the remote profile
|
||||
should be a HSP AG or HFP AG profile */
|
||||
if ((t->profile & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY) == 0) {
|
||||
spa_log_debug(backend->log, "transport %p: Rejecting incoming audio connection to an AG profile", t);
|
||||
goto fail;
|
||||
return;
|
||||
}
|
||||
|
||||
if (t->fd >= 0) {
|
||||
spa_log_debug(backend->log, "transport %p: Rejecting, audio already connected", t);
|
||||
goto fail;
|
||||
return;
|
||||
}
|
||||
|
||||
spa_log_debug(backend->log, "transport %p: codec=%u", t, t->codec);
|
||||
|
@ -1792,18 +1774,18 @@ static void sco_listen_event(struct spa_source *source)
|
|||
voice_config.setting = BT_VOICE_TRANSPARENT;
|
||||
if (setsockopt(sock, SOL_BLUETOOTH, BT_VOICE, &voice_config, sizeof(voice_config)) < 0) {
|
||||
spa_log_error(backend->log, "transport %p: setsockopt(): %s", t, strerror(errno));
|
||||
goto fail;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* First read from the accepted socket is non-blocking and returns a zero length buffer. */
|
||||
if (read(sock, &buff, 1) == -1) {
|
||||
spa_log_error(backend->log, "transport %p: Couldn't authorize SCO connection: %s", t, strerror(errno));
|
||||
goto fail;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
t->fd = sock;
|
||||
t->fd = spa_steal_fd(sock);
|
||||
|
||||
sco_start_source(t);
|
||||
|
||||
|
@ -1823,24 +1805,17 @@ static void sco_listen_event(struct spa_source *source)
|
|||
}
|
||||
|
||||
spa_bt_transport_set_state(t, SPA_BT_TRANSPORT_STATE_PENDING);
|
||||
return;
|
||||
|
||||
fail:
|
||||
if (sock >= 0)
|
||||
close(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
static int sco_listen(struct impl *backend)
|
||||
static void sco_listen(struct impl *backend)
|
||||
{
|
||||
struct sockaddr_sco addr;
|
||||
int sock;
|
||||
uint32_t defer = 1;
|
||||
|
||||
sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, BTPROTO_SCO);
|
||||
spa_autoclose int sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, BTPROTO_SCO);
|
||||
if (sock < 0) {
|
||||
spa_log_error(backend->log, "socket(SEQPACKET, SCO) %m");
|
||||
return -errno;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Bind to local address */
|
||||
|
@ -1850,7 +1825,7 @@ static int sco_listen(struct impl *backend)
|
|||
|
||||
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
spa_log_error(backend->log, "bind(): %m");
|
||||
goto fail_close;
|
||||
return;
|
||||
}
|
||||
|
||||
if (setsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP, &defer, sizeof(defer)) < 0) {
|
||||
|
@ -1863,21 +1838,17 @@ static int sco_listen(struct impl *backend)
|
|||
spa_log_debug(backend->log, "doing listen");
|
||||
if (listen(sock, 1) < 0) {
|
||||
spa_log_error(backend->log, "listen(): %m");
|
||||
goto fail_close;
|
||||
return;
|
||||
}
|
||||
|
||||
backend->sco.func = sco_listen_event;
|
||||
backend->sco.data = backend;
|
||||
backend->sco.fd = sock;
|
||||
backend->sco.fd = spa_steal_fd(sock);
|
||||
backend->sco.mask = SPA_IO_IN;
|
||||
backend->sco.rmask = 0;
|
||||
spa_loop_add_source(backend->main_loop, &backend->sco);
|
||||
|
||||
return sock;
|
||||
|
||||
fail_close:
|
||||
close(sock);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
static int rfcomm_ag_set_volume(struct spa_bt_transport *t, int id)
|
||||
|
@ -2195,7 +2166,7 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag
|
|||
struct rfcomm *rfcomm;
|
||||
struct spa_bt_device *d;
|
||||
struct spa_bt_transport *t = NULL;
|
||||
int fd;
|
||||
spa_autoclose int fd = -1;
|
||||
|
||||
if (!dbus_message_has_signature(m, "oha{sv}")) {
|
||||
spa_log_warn(backend->log, "invalid NewConnection() signature");
|
||||
|
@ -2234,7 +2205,7 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag
|
|||
rfcomm->path = strdup(path);
|
||||
rfcomm->source.func = rfcomm_event;
|
||||
rfcomm->source.data = rfcomm;
|
||||
rfcomm->source.fd = fd;
|
||||
rfcomm->source.fd = spa_steal_fd(fd);
|
||||
rfcomm->source.mask = SPA_IO_IN;
|
||||
rfcomm->source.rmask = 0;
|
||||
/* By default all indicators are enabled */
|
||||
|
|
|
@ -1073,35 +1073,30 @@ static int adapter_init_bus_type(struct spa_bt_monitor *monitor, struct spa_bt_a
|
|||
static int adapter_init_modalias(struct spa_bt_monitor *monitor, struct spa_bt_adapter *d)
|
||||
{
|
||||
char path[1024];
|
||||
FILE *f = NULL;
|
||||
int vendor_id, product_id;
|
||||
const char *str;
|
||||
int res = -EINVAL;
|
||||
|
||||
/* Lookup vendor/product id for the device, if present */
|
||||
str = strrchr(d->path, '/'); /* hciXX */
|
||||
if (str == NULL)
|
||||
goto fail;
|
||||
return -EINVAL;
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/class/bluetooth/%s/device/modalias", str);
|
||||
if ((f = fopen(path, "rbe")) == NULL) {
|
||||
res = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
spa_autoptr(FILE) f = fopen(path, "rbe");
|
||||
if (f == NULL)
|
||||
return -errno;
|
||||
|
||||
if (fscanf(f, "usb:v%04Xp%04X", &vendor_id, &product_id) != 2)
|
||||
goto fail;
|
||||
return -EINVAL;
|
||||
|
||||
d->source_id = SOURCE_ID_USB;
|
||||
d->vendor_id = vendor_id;
|
||||
d->product_id = product_id;
|
||||
fclose(f);
|
||||
|
||||
spa_log_debug(monitor->log, "adapter %p: usb vendor:%04x product:%04x",
|
||||
d, vendor_id, product_id);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (f)
|
||||
fclose(f);
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct spa_bt_adapter *adapter_create(struct spa_bt_monitor *monitor, const char *path)
|
||||
|
@ -2271,11 +2266,10 @@ const struct media_codec **spa_bt_device_get_supported_media_codecs(struct spa_b
|
|||
{
|
||||
struct spa_bt_monitor *monitor = device->monitor;
|
||||
const struct media_codec * const * const media_codecs = monitor->media_codecs;
|
||||
const struct media_codec **supported_codecs;
|
||||
spa_autofree const struct media_codec **supported_codecs = NULL;
|
||||
size_t i, j, size;
|
||||
|
||||
*count = 0;
|
||||
|
||||
size = 8;
|
||||
supported_codecs = malloc(size * sizeof(const struct media_codec *));
|
||||
if (supported_codecs == NULL)
|
||||
|
@ -2296,10 +2290,9 @@ const struct media_codec **spa_bt_device_get_supported_media_codecs(struct spa_b
|
|||
#else
|
||||
p = realloc(supported_codecs, size * sizeof(const struct media_codec *));
|
||||
#endif
|
||||
if (p == NULL) {
|
||||
free(supported_codecs);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
supported_codecs = p;
|
||||
}
|
||||
}
|
||||
|
@ -2307,7 +2300,7 @@ const struct media_codec **spa_bt_device_get_supported_media_codecs(struct spa_b
|
|||
supported_codecs[j] = NULL;
|
||||
*count = j;
|
||||
|
||||
return supported_codecs;
|
||||
return spa_steal_ptr(supported_codecs);
|
||||
}
|
||||
|
||||
static struct spa_bt_remote_endpoint *device_remote_endpoint_find(struct spa_bt_device *device, const char *path)
|
||||
|
@ -3672,7 +3665,7 @@ static bool media_codec_switch_process_current(struct spa_bt_media_codec_switch
|
|||
const struct media_codec *codec;
|
||||
uint8_t config[A2DP_MAX_CAPS_SIZE];
|
||||
enum spa_bt_media_direction direction;
|
||||
char *local_endpoint = NULL;
|
||||
spa_autofree char *local_endpoint = NULL;
|
||||
int res, config_size;
|
||||
spa_autoptr(DBusMessage) m = NULL;
|
||||
DBusMessageIter iter, d;
|
||||
|
@ -3691,19 +3684,19 @@ static bool media_codec_switch_process_current(struct spa_bt_media_codec_switch
|
|||
if (ep == NULL || ep->capabilities == NULL || ep->uuid == NULL) {
|
||||
spa_log_debug(sw->device->monitor->log, "media codec switch %p: endpoint %s not valid, try next",
|
||||
sw, *sw->path_iter);
|
||||
goto next;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Setup and check compatible configuration */
|
||||
if (ep->codec != codec->codec_id) {
|
||||
spa_log_debug(sw->device->monitor->log, "media codec switch %p: different codec, try next", sw);
|
||||
goto next;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(sw->profile & spa_bt_profile_from_uuid(ep->uuid))) {
|
||||
spa_log_debug(sw->device->monitor->log, "media codec switch %p: wrong uuid (%s) for profile, try next",
|
||||
sw, ep->uuid);
|
||||
goto next;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((sw->profile & SPA_BT_PROFILE_A2DP_SINK) || (sw->profile & SPA_BT_PROFILE_BAP_SINK) ) {
|
||||
|
@ -3715,13 +3708,13 @@ static bool media_codec_switch_process_current(struct spa_bt_media_codec_switch
|
|||
} else {
|
||||
spa_log_debug(sw->device->monitor->log, "media codec switch %p: bad profile (%d), try next",
|
||||
sw, sw->profile);
|
||||
goto next;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (media_codec_to_endpoint(codec, direction, &local_endpoint) < 0) {
|
||||
spa_log_debug(sw->device->monitor->log, "media codec switch %p: no endpoint for codec %s, try next",
|
||||
sw, codec->name);
|
||||
goto next;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Each endpoint can be used by only one device at a time (on each adapter) */
|
||||
|
@ -3733,7 +3726,7 @@ static bool media_codec_switch_process_current(struct spa_bt_media_codec_switch
|
|||
if (spa_streq(t->endpoint_path, local_endpoint)) {
|
||||
spa_log_debug(sw->device->monitor->log, "media codec switch %p: endpoint %s in use, try next",
|
||||
sw, local_endpoint);
|
||||
goto next;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3743,7 +3736,7 @@ static bool media_codec_switch_process_current(struct spa_bt_media_codec_switch
|
|||
if (res < 0) {
|
||||
spa_log_debug(sw->device->monitor->log, "media codec switch %p: incompatible capabilities (%d), try next",
|
||||
sw, res);
|
||||
goto next;
|
||||
return false;
|
||||
}
|
||||
config_size = res;
|
||||
|
||||
|
@ -3758,7 +3751,7 @@ static bool media_codec_switch_process_current(struct spa_bt_media_codec_switch
|
|||
m = dbus_message_new_method_call(BLUEZ_SERVICE, ep->path, BLUEZ_MEDIA_ENDPOINT_INTERFACE, "SetConfiguration");
|
||||
if (m == NULL) {
|
||||
spa_log_debug(sw->device->monitor->log, "media codec switch %p: dbus allocation failure, try next", sw);
|
||||
goto next;
|
||||
return false;
|
||||
}
|
||||
|
||||
spa_bt_device_update_last_bluez_action_time(sw->device);
|
||||
|
@ -3776,15 +3769,10 @@ static bool media_codec_switch_process_current(struct spa_bt_media_codec_switch
|
|||
sw->pending = send_with_reply(sw->device->monitor->conn, m, media_codec_switch_reply, sw);
|
||||
if (!sw->pending) {
|
||||
spa_log_error(sw->device->monitor->log, "media codec switch %p: dbus call failure, try next", sw);
|
||||
goto next;
|
||||
return false;
|
||||
}
|
||||
|
||||
free(local_endpoint);
|
||||
return true;
|
||||
|
||||
next:
|
||||
free(local_endpoint);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void media_codec_switch_process(struct spa_bt_media_codec_switch *sw)
|
||||
|
@ -4376,7 +4364,7 @@ static int bluez_register_endpoint_legacy(struct spa_bt_adapter *adapter,
|
|||
{
|
||||
struct spa_bt_monitor *monitor = adapter->monitor;
|
||||
const char *path = adapter->path;
|
||||
char *object_path = NULL;
|
||||
spa_autofree char *object_path = NULL;
|
||||
spa_autoptr(DBusMessage) m = NULL;
|
||||
DBusMessageIter object_it, dict_it;
|
||||
uint8_t caps[A2DP_MAX_CAPS_SIZE];
|
||||
|
@ -4388,20 +4376,18 @@ static int bluez_register_endpoint_legacy(struct spa_bt_adapter *adapter,
|
|||
|
||||
ret = media_codec_to_endpoint(codec, direction, &object_path);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
return ret;
|
||||
|
||||
ret = caps_size = codec->fill_caps(codec, sink ? MEDIA_CODEC_FLAG_SINK : 0, caps);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
return ret;
|
||||
|
||||
m = dbus_message_new_method_call(BLUEZ_SERVICE,
|
||||
path,
|
||||
BLUEZ_MEDIA_INTERFACE,
|
||||
"RegisterEndpoint");
|
||||
if (m == NULL) {
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
}
|
||||
if (m == NULL)
|
||||
return -EIO;
|
||||
|
||||
dbus_message_iter_init_append(m, &object_it);
|
||||
dbus_message_iter_append_basic(&object_it, DBUS_TYPE_OBJECT_PATH, &object_path);
|
||||
|
@ -4414,18 +4400,10 @@ static int bluez_register_endpoint_legacy(struct spa_bt_adapter *adapter,
|
|||
|
||||
dbus_message_iter_close_container(&object_it, &dict_it);
|
||||
|
||||
if (!send_with_reply(monitor->conn, m, bluez_register_endpoint_legacy_reply, adapter)) {
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
free(object_path);
|
||||
if (!send_with_reply(monitor->conn, m, bluez_register_endpoint_legacy_reply, adapter))
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
free(object_path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adapter_register_endpoints_legacy(struct spa_bt_adapter *a)
|
||||
|
@ -4522,7 +4500,6 @@ static DBusHandlerResult object_manager_handler(DBusConnection *c, DBusMessage *
|
|||
struct spa_bt_monitor *monitor = user_data;
|
||||
const struct media_codec * const * const media_codecs = monitor->media_codecs;
|
||||
const char *path, *interface, *member;
|
||||
char *endpoint;
|
||||
DBusMessageIter iter, array;
|
||||
DBusHandlerResult res;
|
||||
int i;
|
||||
|
@ -4572,13 +4549,13 @@ static DBusHandlerResult object_manager_handler(DBusConnection *c, DBusMessage *
|
|||
if (caps_size < 0)
|
||||
continue;
|
||||
|
||||
spa_autofree char *endpoint = NULL;
|
||||
ret = media_codec_to_endpoint(codec, SPA_BT_MEDIA_SINK, &endpoint);
|
||||
if (ret == 0) {
|
||||
spa_log_info(monitor->log, "register media sink codec %s: %s", media_codecs[i]->name, endpoint);
|
||||
append_media_object(&array, endpoint,
|
||||
codec->bap ? SPA_BT_UUID_BAP_SINK : SPA_BT_UUID_A2DP_SINK,
|
||||
codec_id, caps, caps_size);
|
||||
free(endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4587,13 +4564,13 @@ static DBusHandlerResult object_manager_handler(DBusConnection *c, DBusMessage *
|
|||
if (caps_size < 0)
|
||||
continue;
|
||||
|
||||
spa_autofree char *endpoint = NULL;
|
||||
ret = media_codec_to_endpoint(codec, SPA_BT_MEDIA_SOURCE, &endpoint);
|
||||
if (ret == 0) {
|
||||
spa_log_info(monitor->log, "register media source codec %s: %s", media_codecs[i]->name, endpoint);
|
||||
append_media_object(&array, endpoint,
|
||||
codec->bap ? SPA_BT_UUID_BAP_SOURCE : SPA_BT_UUID_A2DP_SOURCE,
|
||||
codec_id, caps, caps_size);
|
||||
free(endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4677,7 +4654,7 @@ static int register_media_endpoint(struct spa_bt_monitor *monitor,
|
|||
if (!endpoint_should_be_registered(monitor, codec, direction))
|
||||
return 0;
|
||||
|
||||
char *object_path = NULL;
|
||||
spa_autofree char *object_path = NULL;
|
||||
int ret = media_codec_to_endpoint(codec, direction, &object_path);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -4687,12 +4664,9 @@ static int register_media_endpoint(struct spa_bt_monitor *monitor,
|
|||
if (!dbus_connection_register_object_path(monitor->conn,
|
||||
object_path,
|
||||
&vtable_endpoint, monitor))
|
||||
{
|
||||
ret = -EIO;
|
||||
}
|
||||
return -EIO;
|
||||
|
||||
free(object_path);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int register_media_application(struct spa_bt_monitor * monitor)
|
||||
|
@ -4738,7 +4712,7 @@ static void unregister_media_endpoint(struct spa_bt_monitor *monitor,
|
|||
if (!endpoint_should_be_registered(monitor, codec, direction))
|
||||
return;
|
||||
|
||||
char *object_path = NULL;
|
||||
spa_autofree char *object_path = NULL;
|
||||
int ret = media_codec_to_endpoint(codec, direction, &object_path);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
@ -4747,8 +4721,6 @@ static void unregister_media_endpoint(struct spa_bt_monitor *monitor,
|
|||
|
||||
if (!dbus_connection_unregister_object_path(monitor->conn, object_path))
|
||||
spa_log_warn(monitor->log, "failed to unregister %s\n", object_path);
|
||||
|
||||
free(object_path);
|
||||
}
|
||||
|
||||
static void unregister_media_application(struct spa_bt_monitor * monitor)
|
||||
|
|
|
@ -29,10 +29,12 @@ int spa_bt_adapter_has_msbc(struct spa_bt_adapter *adapter)
|
|||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/hci_lib.h>
|
||||
|
||||
#include <spa/utils/cleanup.h>
|
||||
|
||||
int spa_bt_adapter_has_msbc(struct spa_bt_adapter *adapter)
|
||||
{
|
||||
int hci_id, res;
|
||||
int sock = -1;
|
||||
int hci_id;
|
||||
spa_autoclose int sock = -1;
|
||||
uint8_t features[8], max_page = 0;
|
||||
struct sockaddr_hci a;
|
||||
const char *str;
|
||||
|
@ -46,28 +48,20 @@ int spa_bt_adapter_has_msbc(struct spa_bt_adapter *adapter)
|
|||
|
||||
sock = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
|
||||
if (sock < 0)
|
||||
goto error;
|
||||
return -errno;
|
||||
|
||||
memset(&a, 0, sizeof(a));
|
||||
a.hci_family = AF_BLUETOOTH;
|
||||
a.hci_dev = hci_id;
|
||||
if (bind(sock, (struct sockaddr *) &a, sizeof(a)) < 0)
|
||||
goto error;
|
||||
return -errno;
|
||||
|
||||
if (hci_read_local_ext_features(sock, 0, &max_page, features, 1000) < 0)
|
||||
goto error;
|
||||
|
||||
close(sock);
|
||||
return -errno;
|
||||
|
||||
adapter->msbc_probed = true;
|
||||
adapter->has_msbc = ((features[2] & LMP_TRSP_SCO) && (features[3] & LMP_ESCO)) ? 1 : 0;
|
||||
return adapter->has_msbc;
|
||||
|
||||
error:
|
||||
res = -errno;
|
||||
if (sock >= 0)
|
||||
close(sock);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
|
||||
#include <spa/utils/string.h>
|
||||
#include <spa/utils/cleanup.h>
|
||||
|
||||
#include "media-codecs.h"
|
||||
|
||||
|
@ -16,7 +17,8 @@ int media_codec_select_config(const struct media_codec_config configs[], size_t
|
|||
uint32_t cap, int preferred_value)
|
||||
{
|
||||
size_t i;
|
||||
int *scores, res;
|
||||
spa_autofree int *scores = NULL;
|
||||
int res;
|
||||
unsigned int max_priority;
|
||||
|
||||
if (n == 0)
|
||||
|
@ -54,9 +56,8 @@ int media_codec_select_config(const struct media_codec_config configs[], size_t
|
|||
}
|
||||
|
||||
if (scores[res] < 0)
|
||||
res = -EINVAL;
|
||||
return -EINVAL;
|
||||
|
||||
free(scores);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -786,7 +786,7 @@ bool mm_answer_call(void *modemmanager, void *user_data, enum cmee_error *error)
|
|||
{
|
||||
struct impl *this = modemmanager;
|
||||
struct call *call_object, *call_tmp;
|
||||
struct dbus_cmd_data *data;
|
||||
spa_autofree struct dbus_cmd_data *data = NULL;
|
||||
spa_autoptr(DBusMessage) m = NULL;
|
||||
|
||||
call_object = NULL;
|
||||
|
@ -828,15 +828,15 @@ bool mm_answer_call(void *modemmanager, void *user_data, enum cmee_error *error)
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return spa_steal_ptr(data), true;
|
||||
}
|
||||
|
||||
bool mm_hangup_call(void *modemmanager, void *user_data, enum cmee_error *error)
|
||||
{
|
||||
struct impl *this = modemmanager;
|
||||
struct call *call_object, *call_tmp;
|
||||
spa_autofree struct dbus_cmd_data *data= NULL;
|
||||
spa_autoptr(DBusMessage) m = NULL;
|
||||
struct dbus_cmd_data *data;
|
||||
|
||||
call_object = NULL;
|
||||
spa_list_for_each(call_tmp, &this->call_list, link) {
|
||||
|
@ -887,7 +887,7 @@ bool mm_hangup_call(void *modemmanager, void *user_data, enum cmee_error *error)
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return spa_steal_ptr(data), true;
|
||||
}
|
||||
|
||||
static void append_basic_variant_dict_entry(DBusMessageIter *dict, const char* key, int variant_type_int, const char* variant_type_str, void* variant) {
|
||||
|
@ -913,7 +913,7 @@ static inline bool is_valid_dial_string_char(char c)
|
|||
bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cmee_error *error)
|
||||
{
|
||||
struct impl *this = modemmanager;
|
||||
struct dbus_cmd_data *data;
|
||||
spa_autofree struct dbus_cmd_data *data = NULL;
|
||||
spa_autoptr(DBusMessage) m = NULL;
|
||||
DBusMessageIter iter, dict;
|
||||
|
||||
|
@ -954,14 +954,14 @@ bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cm
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return spa_steal_ptr(data), true;
|
||||
}
|
||||
|
||||
bool mm_send_dtmf(void *modemmanager, const char *dtmf, void *user_data, enum cmee_error *error)
|
||||
{
|
||||
struct impl *this = modemmanager;
|
||||
struct call *call_object, *call_tmp;
|
||||
struct dbus_cmd_data *data;
|
||||
spa_autofree struct dbus_cmd_data *data = NULL;
|
||||
spa_autoptr(DBusMessage) m = NULL;
|
||||
|
||||
call_object = NULL;
|
||||
|
@ -1015,7 +1015,7 @@ bool mm_send_dtmf(void *modemmanager, const char *dtmf, void *user_data, enum cm
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return spa_steal_ptr(data), true;
|
||||
}
|
||||
|
||||
const char *mm_get_incoming_call_number(void *modemmanager)
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <spa/support/plugin.h>
|
||||
#include <spa/monitor/device.h>
|
||||
#include <spa/monitor/utils.h>
|
||||
#include <spa/utils/cleanup.h>
|
||||
#include <spa/utils/hook.h>
|
||||
#include <spa/utils/type.h>
|
||||
#include <spa/utils/keys.h>
|
||||
|
@ -187,27 +188,21 @@ static int load_conf(struct spa_bt_quirks *this, const char *path)
|
|||
{
|
||||
char *data;
|
||||
struct stat sbuf;
|
||||
int fd = -1;
|
||||
spa_autoclose int fd = -1;
|
||||
|
||||
spa_log_debug(this->log, "loading %s", path);
|
||||
|
||||
if ((fd = open(path, O_CLOEXEC | O_RDONLY)) < 0)
|
||||
goto fail;
|
||||
return -errno;
|
||||
if (fstat(fd, &sbuf) < 0)
|
||||
goto fail;
|
||||
return -errno;
|
||||
if ((data = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
|
||||
goto fail;
|
||||
close(fd);
|
||||
return -errno;
|
||||
|
||||
load_quirks(this, data, sbuf.st_size);
|
||||
munmap(data, sbuf.st_size);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
struct spa_bt_quirks *spa_bt_quirks_create(const struct spa_dict *info, struct spa_log *log)
|
||||
|
|
Loading…
Reference in a new issue