mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
bluez5: Split RFComm from spa_bt_transport
RFComm channel should not be part of the spa_bt_transport as this one may change during HFP connection.
This commit is contained in:
parent
00cce32514
commit
677f122f1d
1 changed files with 73 additions and 36 deletions
|
|
@ -47,13 +47,23 @@ struct spa_bt_backend {
|
||||||
struct spa_loop *main_loop;
|
struct spa_loop *main_loop;
|
||||||
struct spa_dbus *dbus;
|
struct spa_dbus *dbus;
|
||||||
DBusConnection *conn;
|
DBusConnection *conn;
|
||||||
|
|
||||||
|
struct spa_list rfcomm_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct transport_data {
|
struct transport_data {
|
||||||
struct spa_source rfcomm;
|
|
||||||
struct spa_source sco;
|
struct spa_source sco;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rfcomm {
|
||||||
|
struct spa_list link;
|
||||||
|
struct spa_source source;
|
||||||
|
struct spa_bt_backend *backend;
|
||||||
|
struct spa_bt_device *device;
|
||||||
|
struct spa_bt_transport *transport;
|
||||||
|
enum spa_bt_profile profile;
|
||||||
|
};
|
||||||
|
|
||||||
static DBusHandlerResult profile_release(DBusConnection *conn, DBusMessage *m, void *userdata)
|
static DBusHandlerResult profile_release(DBusConnection *conn, DBusMessage *m, void *userdata)
|
||||||
{
|
{
|
||||||
DBusMessage *r;
|
DBusMessage *r;
|
||||||
|
|
@ -69,16 +79,25 @@ static DBusHandlerResult profile_release(DBusConnection *conn, DBusMessage *m, v
|
||||||
return DBUS_HANDLER_RESULT_HANDLED;
|
return DBUS_HANDLER_RESULT_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rfcomm_free(struct rfcomm *rfcomm)
|
||||||
|
{
|
||||||
|
if (rfcomm->transport)
|
||||||
|
spa_bt_transport_free(rfcomm->transport);
|
||||||
|
free(rfcomm);
|
||||||
|
}
|
||||||
|
|
||||||
static void rfcomm_event(struct spa_source *source)
|
static void rfcomm_event(struct spa_source *source)
|
||||||
{
|
{
|
||||||
struct spa_bt_transport *t = source->data;
|
struct rfcomm *rfcomm = source->data;
|
||||||
struct spa_bt_backend *backend = t->backend;
|
struct spa_bt_backend *backend = rfcomm->backend;
|
||||||
|
|
||||||
if (source->rmask & (SPA_IO_HUP | SPA_IO_ERR)) {
|
if (source->rmask & (SPA_IO_HUP | SPA_IO_ERR)) {
|
||||||
spa_log_info(backend->log, NAME": lost RFCOMM connection.");
|
spa_log_info(backend->log, NAME": lost RFCOMM connection.");
|
||||||
if (source->loop)
|
if (source->loop)
|
||||||
spa_loop_remove_source(source->loop, source);
|
spa_loop_remove_source(source->loop, source);
|
||||||
goto fail;
|
spa_list_remove(&rfcomm->link);
|
||||||
|
rfcomm_free(rfcomm);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source->rmask & SPA_IO_IN) {
|
if (source->rmask & SPA_IO_IN) {
|
||||||
|
|
@ -90,7 +109,7 @@ static void rfcomm_event(struct spa_source *source)
|
||||||
len = read(source->fd, buf, 511);
|
len = read(source->fd, buf, 511);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
spa_log_error(backend->log, NAME": RFCOMM read error: %s", strerror(errno));
|
spa_log_error(backend->log, NAME": RFCOMM read error: %s", strerror(errno));
|
||||||
goto fail;
|
return;
|
||||||
}
|
}
|
||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
spa_log_debug(backend->log, NAME": RFCOMM << %s", buf);
|
spa_log_debug(backend->log, NAME": RFCOMM << %s", buf);
|
||||||
|
|
@ -131,10 +150,6 @@ static void rfcomm_event(struct spa_source *source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fail:
|
|
||||||
spa_bt_transport_free(t);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sco_do_accept(struct spa_bt_transport *t)
|
static int sco_do_accept(struct spa_bt_transport *t)
|
||||||
|
|
@ -367,13 +382,6 @@ static int sco_destroy_cb(void *data)
|
||||||
close (td->sco.fd);
|
close (td->sco.fd);
|
||||||
td->sco.fd = -1;
|
td->sco.fd = -1;
|
||||||
}
|
}
|
||||||
if (td->rfcomm.data) {
|
|
||||||
if (td->rfcomm.loop)
|
|
||||||
spa_loop_remove_source(td->rfcomm.loop, &td->rfcomm);
|
|
||||||
shutdown(td->rfcomm.fd, SHUT_RDWR);
|
|
||||||
close (td->rfcomm.fd);
|
|
||||||
td->rfcomm.fd = -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -392,9 +400,9 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag
|
||||||
const char *handler, *path;
|
const char *handler, *path;
|
||||||
char *pathfd;
|
char *pathfd;
|
||||||
enum spa_bt_profile profile;
|
enum spa_bt_profile profile;
|
||||||
|
struct rfcomm *rfcomm;
|
||||||
struct spa_bt_device *d;
|
struct spa_bt_device *d;
|
||||||
struct spa_bt_transport *t;
|
struct spa_bt_transport *t = NULL;
|
||||||
struct transport_data *td;
|
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (!dbus_message_has_signature(m, "oha{sv}")) {
|
if (!dbus_message_has_signature(m, "oha{sv}")) {
|
||||||
|
|
@ -426,13 +434,26 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag
|
||||||
|
|
||||||
spa_log_debug(backend->log, NAME": NewConnection path=%s, fd=%d, profile %s", path, fd, handler);
|
spa_log_debug(backend->log, NAME": NewConnection path=%s, fd=%d, profile %s", path, fd, handler);
|
||||||
|
|
||||||
if ((pathfd = spa_aprintf("%s/fd%d", path, fd)) == NULL)
|
rfcomm = calloc(1, sizeof(struct rfcomm));
|
||||||
|
if (rfcomm == NULL)
|
||||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||||
|
|
||||||
|
rfcomm->backend = backend;
|
||||||
|
rfcomm->profile = profile;
|
||||||
|
rfcomm->device = d;
|
||||||
|
rfcomm->source.func = rfcomm_event;
|
||||||
|
rfcomm->source.data = rfcomm;
|
||||||
|
rfcomm->source.fd = fd;
|
||||||
|
rfcomm->source.mask = SPA_IO_IN;
|
||||||
|
rfcomm->source.rmask = 0;
|
||||||
|
|
||||||
|
if ((pathfd = spa_aprintf("%s/fd%d", path, fd)) == NULL)
|
||||||
|
goto fail_need_memory;
|
||||||
|
|
||||||
t = spa_bt_transport_create(backend->monitor, pathfd, sizeof(struct transport_data));
|
t = spa_bt_transport_create(backend->monitor, pathfd, sizeof(struct transport_data));
|
||||||
if (t == NULL) {
|
if (t == NULL) {
|
||||||
spa_log_warn(backend->log, NAME": can't create transport: %m");
|
spa_log_warn(backend->log, NAME": can't create transport: %m");
|
||||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
goto fail_need_memory;
|
||||||
}
|
}
|
||||||
spa_bt_transport_set_implementation(t, &sco_transport_impl, t);
|
spa_bt_transport_set_implementation(t, &sco_transport_impl, t);
|
||||||
|
|
||||||
|
|
@ -440,14 +461,7 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag
|
||||||
spa_list_append(&t->device->transport_list, &t->device_link);
|
spa_list_append(&t->device->transport_list, &t->device_link);
|
||||||
t->profile = profile;
|
t->profile = profile;
|
||||||
t->backend = backend;
|
t->backend = backend;
|
||||||
|
rfcomm->transport = t;
|
||||||
td = t->user_data;
|
|
||||||
td->rfcomm.func = rfcomm_event;
|
|
||||||
td->rfcomm.data = t;
|
|
||||||
td->rfcomm.fd = fd;
|
|
||||||
td->rfcomm.mask = SPA_IO_IN;
|
|
||||||
td->rfcomm.rmask = 0;
|
|
||||||
spa_loop_add_source(backend->main_loop, &td->rfcomm);
|
|
||||||
|
|
||||||
spa_bt_device_connect_profile(t->device, profile);
|
spa_bt_device_connect_profile(t->device, profile);
|
||||||
|
|
||||||
|
|
@ -456,12 +470,20 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag
|
||||||
spa_log_debug(backend->log, NAME": Transport %s available for profile %s", t->path, handler);
|
spa_log_debug(backend->log, NAME": Transport %s available for profile %s", t->path, handler);
|
||||||
|
|
||||||
if ((r = dbus_message_new_method_return(m)) == NULL)
|
if ((r = dbus_message_new_method_return(m)) == NULL)
|
||||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
goto fail_need_memory;
|
||||||
if (!dbus_connection_send(conn, r, NULL))
|
if (!dbus_connection_send(conn, r, NULL))
|
||||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
goto fail_need_memory;
|
||||||
|
|
||||||
dbus_message_unref(r);
|
dbus_message_unref(r);
|
||||||
|
|
||||||
|
spa_loop_add_source(backend->main_loop, &rfcomm->source);
|
||||||
|
spa_list_append(&backend->rfcomm_list, &rfcomm->link);
|
||||||
|
|
||||||
return DBUS_HANDLER_RESULT_HANDLED;
|
return DBUS_HANDLER_RESULT_HANDLED;
|
||||||
|
|
||||||
|
fail_need_memory:
|
||||||
|
if (rfcomm)
|
||||||
|
rfcomm_free(rfcomm);
|
||||||
|
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusHandlerResult profile_request_disconnection(DBusConnection *conn, DBusMessage *m, void *userdata)
|
static DBusHandlerResult profile_request_disconnection(DBusConnection *conn, DBusMessage *m, void *userdata)
|
||||||
|
|
@ -470,9 +492,9 @@ static DBusHandlerResult profile_request_disconnection(DBusConnection *conn, DBu
|
||||||
DBusMessage *r;
|
DBusMessage *r;
|
||||||
const char *handler, *path;
|
const char *handler, *path;
|
||||||
struct spa_bt_device *d;
|
struct spa_bt_device *d;
|
||||||
struct spa_bt_transport *t, *tmp;
|
|
||||||
enum spa_bt_profile profile;
|
enum spa_bt_profile profile;
|
||||||
DBusMessageIter it[5];
|
DBusMessageIter it[5];
|
||||||
|
struct rfcomm *rfcomm, *rfcomm_tmp;
|
||||||
|
|
||||||
if (!dbus_message_has_signature(m, "o")) {
|
if (!dbus_message_has_signature(m, "o")) {
|
||||||
spa_log_warn(backend->log, NAME": invalid RequestDisconnection() signature");
|
spa_log_warn(backend->log, NAME": invalid RequestDisconnection() signature");
|
||||||
|
|
@ -498,9 +520,16 @@ static DBusHandlerResult profile_request_disconnection(DBusConnection *conn, DBu
|
||||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_list_for_each_safe(t, tmp, &d->transport_list, device_link) {
|
spa_list_for_each_safe(rfcomm, rfcomm_tmp, &backend->rfcomm_list, link) {
|
||||||
if (t->profile == profile)
|
if (rfcomm->device == d && rfcomm->profile == profile) {
|
||||||
spa_bt_transport_free(t);
|
if (rfcomm->source.loop)
|
||||||
|
spa_loop_remove_source(rfcomm->source.loop, &rfcomm->source);
|
||||||
|
shutdown(rfcomm->source.fd, SHUT_RDWR);
|
||||||
|
close (rfcomm->source.fd);
|
||||||
|
rfcomm->source.fd = -1;
|
||||||
|
spa_list_remove(&rfcomm->link);
|
||||||
|
rfcomm_free(rfcomm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
spa_bt_device_check_profiles(d, false);
|
spa_bt_device_check_profiles(d, false);
|
||||||
|
|
||||||
|
|
@ -636,7 +665,7 @@ static int register_profile(struct spa_bt_backend *backend, const char *profile,
|
||||||
|
|
||||||
dbus_connection_send_with_reply(backend->conn, m, &call, -1);
|
dbus_connection_send_with_reply(backend->conn, m, &call, -1);
|
||||||
dbus_pending_call_set_notify(call, register_profile_reply, backend, NULL);
|
dbus_pending_call_set_notify(call, register_profile_reply, backend, NULL);
|
||||||
dbus_message_unref(m);
|
dbus_message_unref(m);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -648,8 +677,14 @@ void backend_native_register_profiles(struct spa_bt_backend *backend)
|
||||||
|
|
||||||
void backend_native_free(struct spa_bt_backend *backend)
|
void backend_native_free(struct spa_bt_backend *backend)
|
||||||
{
|
{
|
||||||
|
struct rfcomm *rfcomm;
|
||||||
|
|
||||||
dbus_connection_unregister_object_path(backend->conn, PROFILE_HSP_AG);
|
dbus_connection_unregister_object_path(backend->conn, PROFILE_HSP_AG);
|
||||||
dbus_connection_unregister_object_path(backend->conn, PROFILE_HSP_HS);
|
dbus_connection_unregister_object_path(backend->conn, PROFILE_HSP_HS);
|
||||||
|
|
||||||
|
spa_list_consume(rfcomm, &backend->rfcomm_list, link)
|
||||||
|
rfcomm_free(rfcomm);
|
||||||
|
|
||||||
free(backend);
|
free(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -673,6 +708,8 @@ struct spa_bt_backend *backend_native_new(struct spa_bt_monitor *monitor,
|
||||||
backend->main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop);
|
backend->main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop);
|
||||||
backend->conn = dbus_connection;
|
backend->conn = dbus_connection;
|
||||||
|
|
||||||
|
spa_list_init(&backend->rfcomm_list);
|
||||||
|
|
||||||
if (!dbus_connection_register_object_path(backend->conn,
|
if (!dbus_connection_register_object_path(backend->conn,
|
||||||
PROFILE_HSP_AG,
|
PROFILE_HSP_AG,
|
||||||
&vtable_profile, backend)) {
|
&vtable_profile, backend)) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue