bluez: Fix gstreamer plugin to reflect the ipc changes.

This commit is contained in:
Luiz Augusto von Dentz 2008-12-16 17:09:57 -03:00 committed by Tim-Philipp Müller
parent 4fd14e4113
commit b03faa59d1

View file

@ -63,7 +63,7 @@ GST_DEBUG_CATEGORY_STATIC (avdtp_sink_debug);
struct bluetooth_data struct bluetooth_data
{ {
struct bt_getcapabilities_rsp caps; /* Bluetooth device caps */ struct bt_get_capabilities_rsp *caps; /* Bluetooth device caps */
guint link_mtu; guint link_mtu;
gchar buffer[BUFFER_SIZE]; /* Codec transfer buffer */ gchar buffer[BUFFER_SIZE]; /* Codec transfer buffer */
@ -110,7 +110,7 @@ static GstStaticPadTemplate avdtp_sink_factory =
static GIOError gst_avdtp_sink_audioservice_send (GstAvdtpSink * self, static GIOError gst_avdtp_sink_audioservice_send (GstAvdtpSink * self,
const bt_audio_msg_header_t * msg); const bt_audio_msg_header_t * msg);
static GIOError gst_avdtp_sink_audioservice_expect (GstAvdtpSink * self, static GIOError gst_avdtp_sink_audioservice_expect (GstAvdtpSink * self,
bt_audio_msg_header_t * outmsg, int expected_type); bt_audio_msg_header_t * outmsg, guint8 expected_name);
static void static void
@ -245,16 +245,38 @@ gst_avdtp_sink_bluetooth_recvmsg_fd (GstAvdtpSink * sink)
return 0; return 0;
} }
static codec_capabilities_t *
gst_avdtp_find_caps (GstAvdtpSink * sink, uint8_t codec_type)
{
struct bt_get_capabilities_rsp *rsp = sink->data->caps;
codec_capabilities_t *codec = (void *) rsp->data;
int bytes_left = rsp->h.length - sizeof (*rsp);
while (bytes_left > 0) {
if (codec->type == codec_type)
break;
bytes_left -= codec->length;
codec = (void *) codec + codec->length;
}
if (bytes_left <= 0)
return NULL;
return codec;
}
static gboolean static gboolean
gst_avdtp_sink_init_sbc_pkt_conf (GstAvdtpSink * sink, gst_avdtp_sink_init_sbc_pkt_conf (GstAvdtpSink * sink,
GstCaps * caps, sbc_capabilities_t * pkt) GstCaps * caps, sbc_capabilities_t * pkt)
{ {
sbc_capabilities_t *cfg = &sink->data->caps.sbc_capabilities; sbc_capabilities_t *cfg;
const GValue *value = NULL; const GValue *value = NULL;
const char *pref, *name; const char *pref, *name;
gint rate, subbands, blocks; gint rate, subbands, blocks;
GstStructure *structure = gst_caps_get_structure (caps, 0); GstStructure *structure = gst_caps_get_structure (caps, 0);
cfg = (void *) gst_avdtp_find_caps (sink, BT_A2DP_CODEC_SBC);
name = gst_structure_get_name (structure); name = gst_structure_get_name (structure);
if (!(IS_SBC (name))) { if (!(IS_SBC (name))) {
@ -589,6 +611,9 @@ gst_avdtp_sink_parse_mpeg_caps (GstAvdtpSink * self, mpeg_capabilities_t * mpeg)
gboolean valid_layer = FALSE; gboolean valid_layer = FALSE;
gboolean mono, stereo; gboolean mono, stereo;
if (!mpeg)
return NULL;
GST_LOG_OBJECT (self, "parsing mpeg caps"); GST_LOG_OBJECT (self, "parsing mpeg caps");
structure = gst_structure_empty_new ("audio/mpeg"); structure = gst_structure_empty_new ("audio/mpeg");
@ -702,14 +727,17 @@ gst_avdtp_sink_parse_mpeg_caps (GstAvdtpSink * self, mpeg_capabilities_t * mpeg)
static gboolean static gboolean
gst_avdtp_sink_update_caps (GstAvdtpSink * self) gst_avdtp_sink_update_caps (GstAvdtpSink * self)
{ {
sbc_capabilities_t *sbc = &self->data->caps.sbc_capabilities; sbc_capabilities_t *sbc;
mpeg_capabilities_t *mpeg = &self->data->caps.mpeg_capabilities; mpeg_capabilities_t *mpeg;
GstStructure *sbc_structure; GstStructure *sbc_structure;
GstStructure *mpeg_structure; GstStructure *mpeg_structure;
gchar *tmp; gchar *tmp;
GST_LOG_OBJECT (self, "updating device caps"); GST_LOG_OBJECT (self, "updating device caps");
sbc = (void *) gst_avdtp_find_caps (self, BT_A2DP_CODEC_SBC);
mpeg = (void *) gst_avdtp_find_caps (self, BT_A2DP_CODEC_MPEG12);
sbc_structure = gst_avdtp_sink_parse_sbc_caps (self, sbc); sbc_structure = gst_avdtp_sink_parse_sbc_caps (self, sbc);
mpeg_structure = gst_avdtp_sink_parse_mpeg_caps (self, mpeg); mpeg_structure = gst_avdtp_sink_parse_mpeg_caps (self, mpeg);
@ -729,14 +757,17 @@ gst_avdtp_sink_update_caps (GstAvdtpSink * self)
static gboolean static gboolean
gst_avdtp_sink_get_capabilities (GstAvdtpSink * self) gst_avdtp_sink_get_capabilities (GstAvdtpSink * self)
{ {
gchar *buf[BT_AUDIO_IPC_PACKET_SIZE]; gchar *buf[BT_SUGGESTED_BUFFER_SIZE];
struct bt_getcapabilities_req *req = (void *) buf; struct bt_get_capabilities_req *req = (void *) buf;
struct bt_getcapabilities_rsp *rsp = (void *) buf; struct bt_get_capabilities_rsp *rsp = (void *) buf;
GIOError io_error; GIOError io_error;
memset (req, 0, BT_AUDIO_IPC_PACKET_SIZE); memset (req, 0, BT_SUGGESTED_BUFFER_SIZE);
req->h.type = BT_REQUEST;
req->h.name = BT_GET_CAPABILITIES;
req->h.length = sizeof (*req);
req->h.msg_type = BT_GETCAPABILITIES_REQ;
if (self->device == NULL) if (self->device == NULL)
return FALSE; return FALSE;
strncpy (req->device, self->device, 18); strncpy (req->device, self->device, 18);
@ -750,19 +781,14 @@ gst_avdtp_sink_get_capabilities (GstAvdtpSink * self)
} }
io_error = gst_avdtp_sink_audioservice_expect (self, io_error = gst_avdtp_sink_audioservice_expect (self,
&rsp->rsp_h.msg_h, BT_GETCAPABILITIES_RSP); &rsp->h, BT_GET_CAPABILITIES);
if (io_error != G_IO_ERROR_NONE) { if (io_error != G_IO_ERROR_NONE) {
GST_ERROR_OBJECT (self, "Error while getting device caps"); GST_ERROR_OBJECT (self, "Error while getting device caps");
return FALSE; return FALSE;
} }
if (rsp->rsp_h.posix_errno != 0) { self->data->caps = g_malloc0 (rsp->h.length);
GST_ERROR_OBJECT (self, "BT_GETCAPABILITIES failed : %s(%d)", memcpy (self->data->caps, rsp, rsp->h.length);
strerror (rsp->rsp_h.posix_errno), rsp->rsp_h.posix_errno);
return FALSE;
}
memcpy (&self->data->caps, rsp, sizeof (*rsp));
if (!gst_avdtp_sink_update_caps (self)) { if (!gst_avdtp_sink_update_caps (self)) {
GST_WARNING_OBJECT (self, "failed to update capabilities"); GST_WARNING_OBJECT (self, "failed to update capabilities");
return FALSE; return FALSE;
@ -882,16 +908,16 @@ failed:
static gboolean static gboolean
gst_avdtp_sink_stream_start (GstAvdtpSink * self) gst_avdtp_sink_stream_start (GstAvdtpSink * self)
{ {
gchar buf[BT_AUDIO_IPC_PACKET_SIZE]; gchar buf[BT_SUGGESTED_BUFFER_SIZE];
struct bt_streamstart_req *req = (void *) buf; struct bt_start_stream_req *req = (void *) buf;
struct bt_streamstart_rsp *rsp = (void *) buf; struct bt_start_stream_rsp *rsp = (void *) buf;
struct bt_streamfd_ind *ind = (void *) buf; struct bt_new_stream_ind *ind = (void *) buf;
GIOError io_error; GIOError io_error;
GST_DEBUG_OBJECT (self, "stream start");
memset (req, 0, sizeof (buf)); memset (req, 0, sizeof (buf));
req->h.msg_type = BT_STREAMSTART_REQ; req->h.type = BT_REQUEST;
req->h.name = BT_START_STREAM;
req->h.length = sizeof (*req);
io_error = gst_avdtp_sink_audioservice_send (self, &req->h); io_error = gst_avdtp_sink_audioservice_send (self, &req->h);
if (io_error != G_IO_ERROR_NONE) { if (io_error != G_IO_ERROR_NONE) {
@ -899,25 +925,14 @@ gst_avdtp_sink_stream_start (GstAvdtpSink * self)
return FALSE; return FALSE;
} }
GST_DEBUG_OBJECT (self, "stream start packet sent");
io_error = gst_avdtp_sink_audioservice_expect (self, io_error = gst_avdtp_sink_audioservice_expect (self,
&rsp->rsp_h.msg_h, BT_STREAMSTART_RSP); &rsp->h, BT_START_STREAM);
if (io_error != G_IO_ERROR_NONE) { if (io_error != G_IO_ERROR_NONE) {
GST_ERROR_OBJECT (self, "Error while stream " "start confirmation"); GST_ERROR_OBJECT (self, "Error while stream " "start confirmation");
return FALSE; return FALSE;
} }
if (rsp->rsp_h.posix_errno != 0) { io_error = gst_avdtp_sink_audioservice_expect (self, &ind->h, BT_NEW_STREAM);
GST_ERROR_OBJECT (self, "BT_STREAMSTART_RSP failed : %s(%d)",
strerror (rsp->rsp_h.posix_errno), rsp->rsp_h.posix_errno);
return FALSE;
}
GST_DEBUG_OBJECT (self, "stream started");
io_error = gst_avdtp_sink_audioservice_expect (self, &ind->h,
BT_STREAMFD_IND);
if (io_error != G_IO_ERROR_NONE) { if (io_error != G_IO_ERROR_NONE) {
GST_ERROR_OBJECT (self, "Error while receiving " "stream filedescriptor"); GST_ERROR_OBJECT (self, "Error while receiving " "stream filedescriptor");
return FALSE; return FALSE;
@ -1008,9 +1023,9 @@ gst_avdtp_sink_init_mp3_pkt_conf (GstAvdtpSink * self, GstCaps * caps,
static gboolean static gboolean
gst_avdtp_sink_configure (GstAvdtpSink * self, GstCaps * caps) gst_avdtp_sink_configure (GstAvdtpSink * self, GstCaps * caps)
{ {
gchar buf[BT_AUDIO_IPC_PACKET_SIZE]; gchar buf[BT_SUGGESTED_BUFFER_SIZE];
struct bt_setconfiguration_req *req = (void *) buf; struct bt_set_configuration_req *req = (void *) buf;
struct bt_setconfiguration_rsp *rsp = (void *) buf; struct bt_set_configuration_rsp *rsp = (void *) buf;
gboolean ret; gboolean ret;
GIOError io_error; GIOError io_error;
gchar *temp; gchar *temp;
@ -1021,16 +1036,18 @@ gst_avdtp_sink_configure (GstAvdtpSink * self, GstCaps * caps)
g_free (temp); g_free (temp);
memset (req, 0, sizeof (buf)); memset (req, 0, sizeof (buf));
req->h.msg_type = BT_SETCONFIGURATION_REQ; req->h.type = BT_REQUEST;
req->h.name = BT_SET_CONFIGURATION;
req->h.length = sizeof (*req);
req->access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE; req->access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE;
strncpy (req->device, self->device, 18); strncpy (req->device, self->device, 18);
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
if (gst_structure_has_name (structure, "audio/x-sbc")) if (gst_structure_has_name (structure, "audio/x-sbc"))
ret = gst_avdtp_sink_init_sbc_pkt_conf (self, caps, &req->sbc_capabilities); ret = gst_avdtp_sink_init_sbc_pkt_conf (self, caps, (void *) &req->codec);
else if (gst_structure_has_name (structure, "audio/mpeg")) else if (gst_structure_has_name (structure, "audio/mpeg"))
ret = gst_avdtp_sink_init_mp3_pkt_conf (self, caps, ret = gst_avdtp_sink_init_mp3_pkt_conf (self, caps, (void *) &req->codec);
&req->mpeg_capabilities);
else else
ret = FALSE; ret = FALSE;
@ -1046,23 +1063,14 @@ gst_avdtp_sink_configure (GstAvdtpSink * self, GstCaps * caps)
return FALSE; return FALSE;
} }
GST_DEBUG_OBJECT (self, "configuration packet sent");
io_error = gst_avdtp_sink_audioservice_expect (self, io_error = gst_avdtp_sink_audioservice_expect (self,
&rsp->rsp_h.msg_h, BT_SETCONFIGURATION_RSP); &rsp->h, BT_SET_CONFIGURATION);
if (io_error != G_IO_ERROR_NONE) { if (io_error != G_IO_ERROR_NONE) {
GST_ERROR_OBJECT (self, "Error while receiving device " "confirmation"); GST_ERROR_OBJECT (self, "Error while receiving device " "confirmation");
return FALSE; return FALSE;
} }
if (rsp->rsp_h.posix_errno != 0) {
GST_ERROR_OBJECT (self, "BT_SETCONFIGURATION_RSP failed : "
"%s(%d)", strerror (rsp->rsp_h.posix_errno), rsp->rsp_h.posix_errno);
return FALSE;
}
self->data->link_mtu = rsp->link_mtu; self->data->link_mtu = rsp->link_mtu;
GST_DEBUG_OBJECT (self, "configuration set");
return TRUE; return TRUE;
} }
@ -1196,13 +1204,19 @@ gst_avdtp_sink_audioservice_send (GstAvdtpSink * self,
{ {
GIOError error; GIOError error;
gsize written; gsize written;
const char *type, *name;
error = g_io_channel_write (self->server, (const gchar *) msg, error = g_io_channel_write (self->server, (const gchar *) msg,
BT_AUDIO_IPC_PACKET_SIZE, &written); BT_SUGGESTED_BUFFER_SIZE, &written);
if (error != G_IO_ERROR_NONE) if (error != G_IO_ERROR_NONE)
GST_ERROR_OBJECT (self, "Error sending data to audio service:" GST_ERROR_OBJECT (self, "Error sending data to audio service:"
" %s(%d)", strerror (errno), errno); " %s(%d)", strerror (errno), errno);
type = bt_audio_strtype (msg->type);
name = bt_audio_strname (msg->name);
GST_DEBUG_OBJECT (self, "sent: %s -> %s", type, name);
return error; return error;
} }
@ -1212,28 +1226,44 @@ gst_avdtp_sink_audioservice_recv (GstAvdtpSink * self,
{ {
GIOError status; GIOError status;
gsize bytes_read; gsize bytes_read;
const char *type; const char *type, *name;
status = g_io_channel_read (self->server, (gchar *) inmsg, status = g_io_channel_read (self->server, (gchar *) inmsg,
BT_AUDIO_IPC_PACKET_SIZE, &bytes_read); BT_SUGGESTED_BUFFER_SIZE, &bytes_read);
if (status != G_IO_ERROR_NONE) { if (status != G_IO_ERROR_NONE) {
GST_ERROR_OBJECT (self, "Error receiving data from " "audio service"); GST_ERROR_OBJECT (self, "Error receiving data from " "audio service");
return status; return status;
} }
type = bt_audio_strmsg (inmsg->msg_type); type = bt_audio_strtype (inmsg->type);
if (!type) { if (!type) {
status = G_IO_ERROR_INVAL; status = G_IO_ERROR_INVAL;
GST_ERROR_OBJECT (self, "Bogus message type %d " GST_ERROR_OBJECT (self, "Bogus message type %d "
"received from audio service", inmsg->msg_type); "received from audio service", inmsg->type);
} }
name = bt_audio_strname (inmsg->name);
if (!name) {
status = G_IO_ERROR_INVAL;
GST_ERROR_OBJECT (self, "Bogus message name %d "
"received from audio service", inmsg->name);
}
if (inmsg->type == BT_ERROR) {
bt_audio_error_t *err = (void *) inmsg;
status = G_IO_ERROR_INVAL;
GST_ERROR_OBJECT (self, "%s failed : "
"%s(%d)", name, strerror (err->posix_errno), err->posix_errno);
}
GST_DEBUG_OBJECT (self, "received: %s <- %s", type, name);
return status; return status;
} }
static GIOError static GIOError
gst_avdtp_sink_audioservice_expect (GstAvdtpSink * self, gst_avdtp_sink_audioservice_expect (GstAvdtpSink * self,
bt_audio_msg_header_t * outmsg, int expected_type) bt_audio_msg_header_t * outmsg, guint8 expected_name)
{ {
GIOError status; GIOError status;
@ -1241,7 +1271,7 @@ gst_avdtp_sink_audioservice_expect (GstAvdtpSink * self,
if (status != G_IO_ERROR_NONE) if (status != G_IO_ERROR_NONE)
return status; return status;
if (outmsg->msg_type != expected_type) if (outmsg->name != expected_name)
status = G_IO_ERROR_INVAL; status = G_IO_ERROR_INVAL;
return status; return status;