mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-25 21:24:16 +08:00
Implement media_transport for HFP_HS_UUID
The transport is used by pulseaudio to suspend and resume streams.
This commit is contained in:
parent
06eb47dec5
commit
021813afd9
@ -42,6 +42,7 @@
|
||||
#include "transport.h"
|
||||
#include "a2dp.h"
|
||||
#include "headset.h"
|
||||
#include "gateway.h"
|
||||
|
||||
#ifndef DBUS_TYPE_UNIX_FD
|
||||
#define DBUS_TYPE_UNIX_FD -1
|
||||
@ -436,6 +437,115 @@ static void cancel_headset(struct media_transport *transport, guint id)
|
||||
headset_cancel_stream(transport->device, id);
|
||||
}
|
||||
|
||||
static void gateway_resume_complete(struct audio_device *dev, GError *err,
|
||||
void *user_data)
|
||||
{
|
||||
struct media_owner *owner = user_data;
|
||||
struct media_request *req = owner->pending;
|
||||
struct media_transport *transport = owner->transport;
|
||||
int fd;
|
||||
uint16_t imtu, omtu;
|
||||
gboolean ret;
|
||||
|
||||
req->id = 0;
|
||||
|
||||
if (dev == NULL)
|
||||
goto fail;
|
||||
|
||||
if (err) {
|
||||
error("Failed to resume gateway: error %s", err->message);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fd = gateway_get_sco_fd(dev);
|
||||
if (fd < 0)
|
||||
goto fail;
|
||||
|
||||
imtu = 48;
|
||||
omtu = 48;
|
||||
|
||||
media_transport_set_fd(transport, fd, imtu, omtu);
|
||||
|
||||
if (g_strstr_len(owner->accesstype, -1, "r") == NULL)
|
||||
imtu = 0;
|
||||
|
||||
if (g_strstr_len(owner->accesstype, -1, "w") == NULL)
|
||||
omtu = 0;
|
||||
|
||||
ret = g_dbus_send_reply(transport->conn, req->msg,
|
||||
DBUS_TYPE_UNIX_FD, &fd,
|
||||
DBUS_TYPE_UINT16, &imtu,
|
||||
DBUS_TYPE_UINT16, &omtu,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (ret == FALSE)
|
||||
goto fail;
|
||||
|
||||
media_owner_remove(owner);
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
media_transport_remove(transport, owner);
|
||||
}
|
||||
|
||||
static guint resume_gateway(struct media_transport *transport,
|
||||
struct media_owner *owner)
|
||||
{
|
||||
struct audio_device *device = transport->device;
|
||||
|
||||
if (transport->in_use == TRUE)
|
||||
goto done;
|
||||
|
||||
transport->in_use = gateway_lock(device, GATEWAY_LOCK_READ |
|
||||
GATEWAY_LOCK_WRITE);
|
||||
if (transport->in_use == FALSE)
|
||||
return 0;
|
||||
|
||||
done:
|
||||
return gateway_request_stream(device, gateway_resume_complete,
|
||||
owner);
|
||||
}
|
||||
|
||||
static gboolean gateway_suspend_complete(gpointer user_data)
|
||||
{
|
||||
struct media_owner *owner = user_data;
|
||||
struct media_transport *transport = owner->transport;
|
||||
|
||||
/* Release always succeeds */
|
||||
if (owner->pending) {
|
||||
owner->pending->id = 0;
|
||||
media_request_reply(owner->pending, transport->conn, 0);
|
||||
media_owner_remove(owner);
|
||||
}
|
||||
|
||||
transport->in_use = FALSE;
|
||||
media_transport_remove(transport, owner);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static guint suspend_gateway(struct media_transport *transport,
|
||||
struct media_owner *owner)
|
||||
{
|
||||
struct audio_device *device = transport->device;
|
||||
static int id = 1;
|
||||
|
||||
if (!owner) {
|
||||
gateway_unlock(device, GATEWAY_LOCK_READ | GATEWAY_LOCK_WRITE);
|
||||
transport->in_use = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
gateway_suspend_stream(device);
|
||||
gateway_unlock(device, GATEWAY_LOCK_READ | GATEWAY_LOCK_WRITE);
|
||||
g_idle_add(gateway_suspend_complete, owner);
|
||||
return id++;
|
||||
}
|
||||
|
||||
static void cancel_gateway(struct media_transport *transport, guint id)
|
||||
{
|
||||
gateway_cancel_stream(transport->device, id);
|
||||
}
|
||||
|
||||
static void media_owner_exit(DBusConnection *connection, void *user_data)
|
||||
{
|
||||
struct media_owner *owner = user_data;
|
||||
@ -672,6 +782,13 @@ static int set_property_headset(struct media_transport *transport,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int set_property_gateway(struct media_transport *transport,
|
||||
const char *property,
|
||||
DBusMessageIter *value)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
|
||||
void *data)
|
||||
{
|
||||
@ -740,6 +857,12 @@ static void get_properties_headset(struct media_transport *transport,
|
||||
dict_append_entry(dict, "Routing", DBUS_TYPE_STRING, &routing);
|
||||
}
|
||||
|
||||
static void get_properties_gateway(struct media_transport *transport,
|
||||
DBusMessageIter *dict)
|
||||
{
|
||||
/* None */
|
||||
}
|
||||
|
||||
void transport_get_properties(struct media_transport *transport,
|
||||
DBusMessageIter *iter)
|
||||
{
|
||||
@ -881,6 +1004,13 @@ struct media_transport *media_transport_create(DBusConnection *conn,
|
||||
transport->nrec_id = headset_add_nrec_cb(device,
|
||||
headset_nrec_changed,
|
||||
transport);
|
||||
} else if (strcasecmp(uuid, HFP_HS_UUID) == 0 ||
|
||||
strcasecmp(uuid, HSP_HS_UUID) == 0) {
|
||||
transport->resume = resume_gateway;
|
||||
transport->suspend = suspend_gateway;
|
||||
transport->cancel = cancel_gateway;
|
||||
transport->get_properties = get_properties_gateway;
|
||||
transport->set_property = set_property_gateway;
|
||||
} else
|
||||
goto fail;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user