#include "hal-log.h"
#include "hal-msg.h"
#include "hal-audio.h"
-#include "../src/shared/util.h"
+#include "hal-utils.h"
#define FIXED_A2DP_PLAYBACK_LATENCY_MS 25
struct timespec *remain);
#endif
-static const audio_codec_get_t audio_codecs[] = {
- codec_sbc,
+static struct {
+ const audio_codec_get_t get_codec;
+ bool loaded;
+} audio_codecs[] = {
+ { .get_codec = codec_aptx, .loaded = false },
+ { .get_codec = codec_sbc, .loaded = false },
};
#define NUM_CODECS (sizeof(audio_codecs) / sizeof(audio_codecs[0]))
goto failed;
}
- if (rsp_len)
- *rsp_len = cmd.len;
+ *rsp_len = cmd.len;
return AUDIO_STATUS_SUCCESS;
return result;
}
-static int register_endpoints(void)
+struct register_state {
+ struct audio_endpoint *ep;
+ bool error;
+};
+
+static void register_endpoint(const struct audio_codec *codec,
+ struct register_state *state)
{
- struct audio_endpoint *ep = &audio_endpoints[0];
- size_t i;
+ struct audio_endpoint *ep = state->ep;
- for (i = 0; i < NUM_CODECS; i++, ep++) {
- const struct audio_codec *codec = audio_codecs[i]();
+ /* don't even try to register more endpoints if one failed */
+ if (state->error)
+ return;
- if (!codec)
- return AUDIO_STATUS_FAILED;
+ ep->id = ipc_open_cmd(codec);
- ep->id = ipc_open_cmd(codec);
+ if (!ep->id) {
+ state->error = true;
+ error("Failed to register endpoint");
+ return;
+ }
- if (!ep->id)
- return AUDIO_STATUS_FAILED;
+ ep->codec = codec;
+ ep->codec_data = NULL;
+ ep->fd = -1;
- ep->codec = codec;
- ep->codec_data = NULL;
- ep->fd = -1;
+ state->ep++;
+}
+
+static int register_endpoints(void)
+{
+ struct register_state state;
+ unsigned int i;
+
+ state.ep = &audio_endpoints[0];
+ state.error = false;
+
+ for (i = 0; i < NUM_CODECS; i++) {
+ const struct audio_codec *codec = audio_codecs[i].get_codec();
+
+ if (!audio_codecs[i].loaded)
+ continue;
+
+ register_endpoint(codec, &state);
}
- return AUDIO_STATUS_SUCCESS;
+ return state.error ? AUDIO_STATUS_FAILED : AUDIO_STATUS_SUCCESS;
}
static void unregister_endpoints(void)
if (!ep) {
error("Cound not find opened endpoint");
- return false;
+ goto failed;
}
*epp = ep;
ep->samples = 0;
ep->resync = false;
- if (ep->codec->update_qos)
- ep->codec->update_qos(ep->codec_data, QOS_POLICY_DEFAULT);
+ ep->codec->update_qos(ep->codec_data, QOS_POLICY_DEFAULT);
return true;
}
frames = bytes / (2 * sizeof(int16_t));
for (i = 0; i < frames; i++) {
- int16_t l = le16_to_cpu(get_unaligned(&input[i * 2]));
- int16_t r = le16_to_cpu(get_unaligned(&input[i * 2 + 1]));
+ int16_t l = get_le16(&input[i * 2]);
+ int16_t r = get_le16(&input[i * 2 + 1]);
- put_unaligned(cpu_to_le16((l + r) / 2), &output[i]);
+ put_le16((l + r) / 2, &output[i]);
}
}
if (diff > MAX_DELAY) {
warn("lag is %jums, resyncing", diff / 1000);
- if (ep->codec->update_qos)
- ep->codec->update_qos(ep->codec_data,
+ ep->codec->update_qos(ep->codec_data,
QOS_POLICY_DECREASE);
ep->resync = true;
}
static int audio_close(hw_device_t *device)
{
struct a2dp_audio_dev *a2dp_dev = (struct a2dp_audio_dev *)device;
+ unsigned int i;
DBG("");
unregister_endpoints();
+ for (i = 0; i < NUM_CODECS; i++) {
+ const struct audio_codec *codec = audio_codecs[i].get_codec();
+
+ if (!audio_codecs[i].loaded)
+ continue;
+
+ if (codec->unload)
+ codec->unload();
+
+ audio_codecs[i].loaded = false;
+ }
+
shutdown(listen_sk, SHUT_RDWR);
shutdown(audio_sk, SHUT_RDWR);
/* Check if socket is still alive. Empty while loop.*/
while (poll(&pfd, 1, -1) < 0 && errno == EINTR);
- if (pfd.revents & (POLLHUP | POLLERR | POLLNVAL)) {
- info("Audio HAL: Socket closed");
+ info("Audio HAL: Socket closed");
- pthread_mutex_lock(&sk_mutex);
- close(audio_sk);
- audio_sk = -1;
- pthread_mutex_unlock(&sk_mutex);
- }
+ pthread_mutex_lock(&sk_mutex);
+ close(audio_sk);
+ audio_sk = -1;
+ pthread_mutex_unlock(&sk_mutex);
}
/* audio_sk is closed at this point, just cleanup endpoints states */
hw_device_t **device)
{
struct a2dp_audio_dev *a2dp_dev;
+ size_t i;
int err;
DBG("");
a2dp_dev->dev.close_input_stream = audio_close_input_stream;
a2dp_dev->dev.dump = audio_dump;
+ for (i = 0; i < NUM_CODECS; i++) {
+ const struct audio_codec *codec = audio_codecs[i].get_codec();
+
+ if (codec->load && !codec->load())
+ continue;
+
+ audio_codecs[i].loaded = true;
+ }
+
/*
* Note that &a2dp_dev->dev.common is the same pointer as a2dp_dev.
* This results from the structure of following structs:a2dp_audio_dev,