From ddc558fbe9bbabc9814796d3c0a1ff80cb268279 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 15 Jan 2014 19:03:50 +0100 Subject: [PATCH] android/hal-audio: Add support to open output stream This patch adds support to open output stream via Audio IPC. Since only SBC is supported, we always try to open stream for first endpoint only which is enough. --- android/hal-audio.c | 109 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 21 deletions(-) diff --git a/android/hal-audio.c b/android/hal-audio.c index 45e5aead4..75402abe4 100644 --- a/android/hal-audio.c +++ b/android/hal-audio.c @@ -87,9 +87,23 @@ struct audio_endpoint { static struct audio_endpoint audio_endpoints[MAX_AUDIO_ENDPOINTS]; +enum a2dp_state_t { + AUDIO_A2DP_STATE_NONE, + AUDIO_A2DP_STATE_STANDBY, + AUDIO_A2DP_STATE_SUSPENDED, + AUDIO_A2DP_STATE_STARTED +}; + +struct a2dp_stream_out { + struct audio_stream_out stream; + + struct audio_endpoint *ep; + enum a2dp_state_t audio_state; +}; + struct a2dp_audio_dev { struct audio_hw_device dev; - struct audio_stream_out *out; + struct a2dp_stream_out *out; }; static const a2dp_sbc_t sbc_presets[] = { @@ -354,6 +368,38 @@ static int ipc_close_cmd(uint8_t endpoint_id) return result; } +static int ipc_open_stream_cmd(uint8_t endpoint_id, + struct audio_preset **caps) +{ + char buf[BLUEZ_AUDIO_MTU]; + struct audio_cmd_open_stream cmd; + struct audio_rsp_open_stream *rsp = + (struct audio_rsp_open_stream *) &buf; + size_t rsp_len = sizeof(buf); + int result; + + DBG(""); + + if (!caps) + return AUDIO_STATUS_FAILED; + + cmd.id = endpoint_id; + + result = audio_ipc_cmd(AUDIO_SERVICE_ID, AUDIO_OP_OPEN_STREAM, + sizeof(cmd), &cmd, &rsp_len, rsp, NULL); + + if (result == AUDIO_STATUS_SUCCESS) { + size_t buf_len = sizeof(struct audio_preset) + + rsp->preset[0].len; + *caps = malloc(buf_len); + memcpy(*caps, &rsp->preset, buf_len); + } else { + *caps = NULL; + } + + return result; +} + static int register_endpoints(void) { struct audio_endpoint *ep = &audio_endpoints[0]; @@ -595,35 +641,56 @@ static int audio_open_output_stream(struct audio_hw_device *dev, { struct a2dp_audio_dev *a2dp_dev = (struct a2dp_audio_dev *) dev; - struct audio_stream_out *out; + struct a2dp_stream_out *out; + struct audio_preset *preset; - out = calloc(1, sizeof(struct audio_stream_out)); + out = calloc(1, sizeof(struct a2dp_stream_out)); if (!out) return -ENOMEM; DBG(""); - out->common.get_sample_rate = out_get_sample_rate; - out->common.set_sample_rate = out_set_sample_rate; - out->common.get_buffer_size = out_get_buffer_size; - out->common.get_channels = out_get_channels; - out->common.get_format = out_get_format; - out->common.set_format = out_set_format; - out->common.standby = out_standby; - out->common.dump = out_dump; - out->common.set_parameters = out_set_parameters; - out->common.get_parameters = out_get_parameters; - out->common.add_audio_effect = out_add_audio_effect; - out->common.remove_audio_effect = out_remove_audio_effect; - out->get_latency = out_get_latency; - out->set_volume = out_set_volume; - out->write = out_write; - out->get_render_position = out_get_render_position; - - *stream_out = out; + out->stream.common.get_sample_rate = out_get_sample_rate; + out->stream.common.set_sample_rate = out_set_sample_rate; + out->stream.common.get_buffer_size = out_get_buffer_size; + out->stream.common.get_channels = out_get_channels; + out->stream.common.get_format = out_get_format; + out->stream.common.set_format = out_set_format; + out->stream.common.standby = out_standby; + out->stream.common.dump = out_dump; + out->stream.common.set_parameters = out_set_parameters; + out->stream.common.get_parameters = out_get_parameters; + out->stream.common.add_audio_effect = out_add_audio_effect; + out->stream.common.remove_audio_effect = out_remove_audio_effect; + out->stream.get_latency = out_get_latency; + out->stream.set_volume = out_set_volume; + out->stream.write = out_write; + out->stream.get_render_position = out_get_render_position; + + /* TODO: for now we always use endpoint 0 */ + out->ep = &audio_endpoints[0]; + + if (ipc_open_stream_cmd(out->ep->id, &preset) != AUDIO_STATUS_SUCCESS) + goto fail; + + if (!preset) + goto fail; + + /* TODO: initialize codec using received audio_preset */ + + free(preset); + + *stream_out = &out->stream; a2dp_dev->out = out; + out->audio_state = AUDIO_A2DP_STATE_STANDBY; + return 0; + +fail: + free(out); + *stream_out = NULL; + return -EIO; } static void audio_close_output_stream(struct audio_hw_device *dev, -- 2.47.3