Implement media_transport for HFP_HS_UUID

The transport is used by pulseaudio to suspend and resume streams.
This commit is contained in:
Frédéric Dalleau 2011-08-22 17:30:47 +02:00 committed by Johan Hedberg
parent 06eb47dec5
commit 021813afd9

View File

@ -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;