From 136511fbc80320400fc0de58b3766c389f92a887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Danis?= Date: Thu, 8 Apr 2021 15:38:25 +0200 Subject: [PATCH] bluez5: backend-ofono: Enable SCO deferred socket The incoming SCO socket should be first read to authorize the connection. --- spa/plugins/bluez5/backend-ofono.c | 42 ++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/spa/plugins/bluez5/backend-ofono.c b/spa/plugins/bluez5/backend-ofono.c index 2f0781194..0604a94d5 100644 --- a/spa/plugins/bluez5/backend-ofono.c +++ b/spa/plugins/bluez5/backend-ofono.c @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -88,6 +89,7 @@ struct transport_data { #define OFONO_ERROR_INVALID_ARGUMENTS "org.ofono.Error.InvalidArguments" #define OFONO_ERROR_NOT_IMPLEMENTED "org.ofono.Error.NotImplemented" #define OFONO_ERROR_IN_USE "org.ofono.Error.InUse" +#define OFONO_ERROR_FAILED "org.ofono.Error.Failed" static void ofono_transport_get_mtu(struct impl *backend, struct spa_bt_transport *t) { @@ -407,6 +409,35 @@ static void sco_event(struct spa_source *source) } } +static int enable_sco_socket(int sock) +{ + char c; + struct pollfd pfd; + + if (sock < 0) + return ENOTCONN; + + memset(&pfd, 0, sizeof(pfd)); + pfd.fd = sock; + pfd.events = POLLOUT; + + if (poll(&pfd, 1, 0) < 0) + return errno; + + /* + * If socket already writable then it is not in defer setup state, + * otherwise it needs to be read to authorize the connection. + */ + if ((pfd.revents & POLLOUT)) + return 0; + + /* Enable socket by reading 1 byte */ + if (read(sock, &c, 1) < 0) + return errno; + + return 0; +} + static DBusHandlerResult ofono_new_audio_connection(DBusConnection *conn, DBusMessage *m, void *userdata) { struct impl *backend = userdata; @@ -428,6 +459,17 @@ static DBusHandlerResult ofono_new_audio_connection(DBusConnection *conn, DBusMe t = spa_bt_transport_find(backend->monitor, path); if (t && (t->profile & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY)) { + int err; + + err = enable_sco_socket(fd); + if (err) { + spa_log_error(backend->log, NAME": transport %p: Couldn't authorize SCO connection: %s", t, strerror(err)); + r = dbus_message_new_error(m, OFONO_ERROR_FAILED, "SCO authorization failed"); + shutdown(fd, SHUT_RDWR); + close(fd); + goto fail; + } + t->fd = fd; t->codec = codec;