Those patches adds function to handle send/receive msg on audio IPC.
Also do some small changes.
Not that since we do not yet support AUDIO_OP_OPEN, audio socket will be
reseted just after connect.
Lukasz Rymanowski (4):
android/audio: Prefix error log with "a2dp"
android/audio: Change mainloop handle in ipc_handler
android/audio: Add skeleton for open_endpoint_cmd function
android/audio: Add audio_ipc_cmd
android/Makefile.am | 1 +
android/hal-audio.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 186 insertions(+), 11 deletions(-)
--
1.8.4
Hi Lukasz,
On Thu, Jan 9, 2014 at 1:45 PM, Lukasz Rymanowski
<[email protected]> wrote:
> Make sure we wait 1 sec after each loop iteration.
> It is important in case of failure that we do not overload cpu.
>
> ---
> android/hal-audio.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/android/hal-audio.c b/android/hal-audio.c
> index 7a7c111..4a12bcb 100644
> --- a/android/hal-audio.c
> +++ b/android/hal-audio.c
> @@ -465,15 +465,14 @@ failed:
>
> static void *ipc_handler(void *data)
> {
> - bool done = false;
> struct pollfd pfd;
> + bool done;
>
> DBG("");
>
> - while (!done) {
> + for (done = false; !done; sleep(1)) {
This is getting bad really quickly, I did not realize there was a
sleep in it but usually the use of it means we are doing something
wrong which I suspect it has to do with either bind or listen failing
since you are executing them in a loop, in that case I would suggest
to start the listen socket on audio_open and only do the accept in the
thread.
--
Luiz Augusto von Dentz
Hi Lukasz,
On Thu, Jan 9, 2014 at 1:45 PM, Lukasz Rymanowski
<[email protected]> wrote:
> ---
> android/hal-audio.c | 16 +++++++++-------
> 1 file changed, 9 insertions(+), 7 deletions(-)
>
> diff --git a/android/hal-audio.c b/android/hal-audio.c
> index 59a8269..7a7c111 100644
> --- a/android/hal-audio.c
> +++ b/android/hal-audio.c
> @@ -423,7 +423,8 @@ static bool create_audio_ipc(void)
> sk = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
> if (sk < 0) {
> err = errno;
> - error("Failed to create socket: %d (%s)", err, strerror(err));
> + error("a2dp: Failed to create socket: %d (%s)", err,
> + strerror(err));
> return false;
> }
>
> @@ -435,13 +436,14 @@ static bool create_audio_ipc(void)
>
> if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
> err = errno;
> - error("Failed to bind socket: %d (%s)", err, strerror(err));
> + error("a2dp: Failed to bind socket: %d (%s)", err,
> + strerror(err));
> goto failed;
> }
>
> if (listen(sk, 1) < 0) {
> err = errno;
> - error("Failed to listen on the socket: %d (%s)", err,
> + error("a2dp: Failed to listen on the socket: %d (%s)", err,
> strerror(err));
> goto failed;
> }
> @@ -449,7 +451,7 @@ static bool create_audio_ipc(void)
> audio_sk = accept(sk, NULL, NULL);
> if (audio_sk < 0) {
> err = errno;
> - error("Failed to accept socket: %d (%s)", err, strerror(err));
> + error("a2dp: Failed to accept socket: %d (%s)", err, strerror(err));
> goto failed;
> }
>
> @@ -470,7 +472,7 @@ static void *ipc_handler(void *data)
>
> while (!done) {
> if(!create_audio_ipc()) {
> - error("Failed to create listening socket");
> + error("a2dp: Failed to create listening socket");
> sleep(1);
> continue;
> }
> @@ -511,7 +513,7 @@ static int audio_open(const hw_module_t *module, const char *name,
> DBG("");
>
> if (strcmp(name, AUDIO_HARDWARE_INTERFACE)) {
> - error("interface %s not matching [%s]", name,
> + error("ad2p: interface %s not matching [%s]", name,
> AUDIO_HARDWARE_INTERFACE);
> return -EINVAL;
> }
> @@ -547,7 +549,7 @@ static int audio_open(const hw_module_t *module, const char *name,
> err = pthread_create(&ipc_th, NULL, ipc_handler, NULL);
> if (err < 0) {
> ipc_th = 0;
> - error("Failed to start Audio IPC thread: %d (%s)",
> + error("a2dp: Failed to start Audio IPC thread: %d (%s)",
> -err, strerror(-err));
> return (-err);
> }
> --
> 1.8.4
I prefer you use the term Audio as prefix e.g. Audo: Failed to start
IPC thread as this may be used for more than just A2DP.
--
Luiz Augusto von Dentz
Adds function to handle send/receive on audio_sk
---
android/Makefile.am | 1 +
android/hal-audio.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 166 insertions(+), 2 deletions(-)
diff --git a/android/Makefile.am b/android/Makefile.am
index 0a32a95..94e5329 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -117,6 +117,7 @@ android_android_tester_LDFLAGS = -pthread
noinst_LTLIBRARIES += android/libaudio-internal.la
android_libaudio_internal_la_SOURCES = android/audio-msg.h \
+ android/hal-msg.h \
android/hal-audio.c \
android/hardware/audio.h \
android/hardware/audio_effect.h \
diff --git a/android/hal-audio.c b/android/hal-audio.c
index 95efa89..e515f53 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -31,12 +31,14 @@
#include "audio-msg.h"
#include "hal-log.h"
+#include "hal-msg.h"
static int audio_sk = -1;
static bool close_thread = false;
static pthread_t ipc_th = 0;
static pthread_mutex_t close_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t sk_mutex = PTHREAD_MUTEX_INITIALIZER;
struct a2dp_audio_dev {
struct audio_hw_device dev;
@@ -412,13 +414,174 @@ static int audio_close(hw_device_t *device)
return 0;
}
-static int open_endpoint_cmd(void)
+static int audio_ipc_cmd(uint8_t service_id, uint8_t opcode, uint16_t len,
+ void *param, size_t *rsp_len, void *rsp, int *fd)
{
- DBG("Not Implemented");
+ ssize_t ret;
+ struct msghdr msg;
+ struct iovec iv[2];
+ struct hal_hdr cmd;
+ char cmsgbuf[CMSG_SPACE(sizeof(int))];
+ struct hal_status s;
+ size_t s_len = sizeof(s);
+
+ if (audio_sk < 0) {
+ error("a2dp: Invalid cmd socket passed to audio_sk");
+ goto failed;
+ }
+
+ if (!rsp || !rsp_len) {
+ memset(&s, 0, s_len);
+ rsp_len = &s_len;
+ rsp = &s;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&cmd, 0, sizeof(cmd));
+
+ cmd.service_id = service_id;
+ cmd.opcode = opcode;
+ cmd.len = len;
+
+ iv[0].iov_base = &cmd;
+ iv[0].iov_len = sizeof(cmd);
+
+ iv[1].iov_base = param;
+ iv[1].iov_len = len;
+
+ msg.msg_iov = iv;
+ msg.msg_iovlen = 2;
+
+ pthread_mutex_lock(&sk_mutex);
+
+ ret = sendmsg(audio_sk, &msg, 0);
+ if (ret < 0) {
+ error("a2dp: Sending command failed:%s", strerror(errno));
+ pthread_mutex_unlock(&sk_mutex);
+ goto failed;
+ }
+
+ /* socket was shutdown */
+ if (ret == 0) {
+ error("a2dp: Command socket closed");
+ goto failed;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&cmd, 0, sizeof(cmd));
+
+ iv[0].iov_base = &cmd;
+ iv[0].iov_len = sizeof(cmd);
+
+ iv[1].iov_base = rsp;
+ iv[1].iov_len = *rsp_len;
+
+ msg.msg_iov = iv;
+ msg.msg_iovlen = 2;
+
+ if (fd) {
+ memset(cmsgbuf, 0, sizeof(cmsgbuf));
+ msg.msg_control = cmsgbuf;
+ msg.msg_controllen = sizeof(cmsgbuf);
+ }
+
+ ret = recvmsg(audio_sk, &msg, 0);
+ if (ret < 0) {
+ error("a2dp: Receiving command response failed:%s",
+ strerror(errno));
+ pthread_mutex_unlock(&sk_mutex);
+ goto failed;
+ }
+
+ pthread_mutex_unlock(&sk_mutex);
+
+ if (ret < (ssize_t) sizeof(cmd)) {
+ error("a2dp: Too small response received(%zd bytes)", ret);
+ goto failed;
+ }
+
+ if (cmd.service_id != service_id) {
+ error("a2dp: Invalid service id (%u vs %u)", cmd.service_id,
+ service_id);
+ goto failed;
+ }
+
+ if (ret != (ssize_t) (sizeof(cmd) + cmd.len)) {
+ error("a2dp: Malformed response received(%zd bytes)", ret);
+ goto failed;
+ }
+
+ if (cmd.opcode != opcode && cmd.opcode != AUDIO_OP_STATUS) {
+ error("a2dp: Invalid opcode received (%u vs %u)",
+ cmd.opcode, opcode);
+ goto failed;
+ }
+
+ if (cmd.opcode == AUDIO_OP_STATUS) {
+ struct hal_status *s = rsp;
+
+ if (sizeof(*s) != cmd.len) {
+ error("a2dp: Invalid status length");
+ goto failed;
+ }
+
+ if (s->code == AUDIO_STATUS_SUCCESS) {
+ error("a2dp: Invalid success status response");
+ goto failed;
+ }
+
+ return s->code;
+ }
+
+ /* Receive auxiliary data in msg */
+ if (fd) {
+ struct cmsghdr *cmsg;
+
+ *fd = -1;
+
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
+ cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_level == SOL_SOCKET
+ && cmsg->cmsg_type == SCM_RIGHTS) {
+ memcpy(fd, CMSG_DATA(cmsg), sizeof(int));
+ break;
+ }
+ }
+ }
+
+ if (rsp_len)
+ *rsp_len = cmd.len;
+ return AUDIO_STATUS_SUCCESS;
+
+failed:
+ /* Some serious issue happen on IPC - recover */
+ shutdown(audio_sk, SHUT_RDWR);
return AUDIO_STATUS_FAILED;
}
+static int open_endpoint_cmd(void)
+{
+ struct audio_rsp_open rsp;
+ uint8_t buf[sizeof(struct audio_cmd_open) +
+ sizeof(struct audio_preset)];
+ size_t rsp_len = sizeof(rsp);
+ int result;
+
+ DBG("");
+
+ memset(&buf, 0, sizeof(buf));
+
+ /* TODO: Fill in buf here with smth */
+
+ result = audio_ipc_cmd(AUDIO_SERVICE_ID, AUDIO_OP_OPEN, sizeof(buf), buf,
+ &rsp_len, &rsp, NULL);
+
+ /*TODO: Read response and store endoint id */
+
+ return result;
+}
+
static bool create_audio_ipc(void)
{
struct sockaddr_un addr;
--
1.8.4
---
android/hal-audio.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/android/hal-audio.c b/android/hal-audio.c
index 4a12bcb..95efa89 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -412,6 +412,13 @@ static int audio_close(hw_device_t *device)
return 0;
}
+static int open_endpoint_cmd(void)
+{
+ DBG("Not Implemented");
+
+ return AUDIO_STATUS_FAILED;
+}
+
static bool create_audio_ipc(void)
{
struct sockaddr_un addr;
@@ -478,7 +485,10 @@ static void *ipc_handler(void *data)
DBG("Audio IPC: Connected");
- /* TODO: Register ENDPOINT here */
+ if (open_endpoint_cmd() == AUDIO_STATUS_FAILED) {
+ error("a2dp: failed to open endpoint");
+ continue;
+ }
memset(&pfd, 0, sizeof(pfd));
pfd.fd = audio_sk;
--
1.8.4
Make sure we wait 1 sec after each loop iteration.
It is important in case of failure that we do not overload cpu.
---
android/hal-audio.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/android/hal-audio.c b/android/hal-audio.c
index 7a7c111..4a12bcb 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -465,15 +465,14 @@ failed:
static void *ipc_handler(void *data)
{
- bool done = false;
struct pollfd pfd;
+ bool done;
DBG("");
- while (!done) {
+ for (done = false; !done; sleep(1)) {
if(!create_audio_ipc()) {
error("a2dp: Failed to create listening socket");
- sleep(1);
continue;
}
--
1.8.4
---
android/hal-audio.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/android/hal-audio.c b/android/hal-audio.c
index 59a8269..7a7c111 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -423,7 +423,8 @@ static bool create_audio_ipc(void)
sk = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
if (sk < 0) {
err = errno;
- error("Failed to create socket: %d (%s)", err, strerror(err));
+ error("a2dp: Failed to create socket: %d (%s)", err,
+ strerror(err));
return false;
}
@@ -435,13 +436,14 @@ static bool create_audio_ipc(void)
if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
err = errno;
- error("Failed to bind socket: %d (%s)", err, strerror(err));
+ error("a2dp: Failed to bind socket: %d (%s)", err,
+ strerror(err));
goto failed;
}
if (listen(sk, 1) < 0) {
err = errno;
- error("Failed to listen on the socket: %d (%s)", err,
+ error("a2dp: Failed to listen on the socket: %d (%s)", err,
strerror(err));
goto failed;
}
@@ -449,7 +451,7 @@ static bool create_audio_ipc(void)
audio_sk = accept(sk, NULL, NULL);
if (audio_sk < 0) {
err = errno;
- error("Failed to accept socket: %d (%s)", err, strerror(err));
+ error("a2dp: Failed to accept socket: %d (%s)", err, strerror(err));
goto failed;
}
@@ -470,7 +472,7 @@ static void *ipc_handler(void *data)
while (!done) {
if(!create_audio_ipc()) {
- error("Failed to create listening socket");
+ error("a2dp: Failed to create listening socket");
sleep(1);
continue;
}
@@ -511,7 +513,7 @@ static int audio_open(const hw_module_t *module, const char *name,
DBG("");
if (strcmp(name, AUDIO_HARDWARE_INTERFACE)) {
- error("interface %s not matching [%s]", name,
+ error("ad2p: interface %s not matching [%s]", name,
AUDIO_HARDWARE_INTERFACE);
return -EINVAL;
}
@@ -547,7 +549,7 @@ static int audio_open(const hw_module_t *module, const char *name,
err = pthread_create(&ipc_th, NULL, ipc_handler, NULL);
if (err < 0) {
ipc_th = 0;
- error("Failed to start Audio IPC thread: %d (%s)",
+ error("a2dp: Failed to start Audio IPC thread: %d (%s)",
-err, strerror(-err));
return (-err);
}
--
1.8.4