From e1debdf2d498d4106abe560e439801475b7f474c Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 21 Oct 2013 20:56:42 +0200 Subject: [PATCH] android/hal: Add initial code for sending commands This will be used by all HAL modules to send commands and get response from daemon. In case of any protocol error abort. If non-null fd pointer is passed auxiliary data with passed FD will be received as part of response. --- android/hal-ipc.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ android/hal-ipc.h | 3 ++ 2 files changed, 110 insertions(+) diff --git a/android/hal-ipc.c b/android/hal-ipc.c index 6db67f21c..5b77adf7b 100644 --- a/android/hal-ipc.c +++ b/android/hal-ipc.c @@ -37,6 +37,8 @@ static int cmd_sk = -1; static int notif_sk = -1; +static pthread_mutex_t cmd_sk_mutex = PTHREAD_MUTEX_INITIALIZER; + static int accept_connection(int sk) { int err; @@ -135,3 +137,108 @@ void hal_ipc_cleanup(void) close(notif_sk); notif_sk = -1; } + +int hal_ipc_cmd(uint8_t service_id, uint8_t opcode, uint16_t len, void *param, + size_t rsp_len, void *rsp, int *fd) +{ + ssize_t ret; + struct msghdr msg; + struct iovec iv[2]; + struct hal_msg_hdr hal_msg; + char cmsgbuf[CMSG_SPACE(sizeof(int))]; + + if (cmd_sk < 0) + return -EBADF; + + memset(&msg, 0, sizeof(msg)); + memset(&hal_msg, 0, sizeof(hal_msg)); + + hal_msg.service_id = service_id; + hal_msg.opcode = opcode; + hal_msg.len = len; + + iv[0].iov_base = &hal_msg; + iv[0].iov_len = sizeof(hal_msg); + + iv[1].iov_base = param; + iv[1].iov_len = len; + + msg.msg_iov = iv; + msg.msg_iovlen = 2; + + pthread_mutex_lock(&cmd_sk_mutex); + + ret = sendmsg(cmd_sk, &msg, 0); + if (ret < 0) { + error("Sending command failed, aborting :%s", strerror(errno)); + pthread_mutex_unlock(&cmd_sk_mutex); + exit(EXIT_FAILURE); + } + + memset(&msg, 0, sizeof(msg)); + memset(&hal_msg, 0, sizeof(hal_msg)); + + iv[0].iov_base = &hal_msg; + iv[0].iov_len = sizeof(hal_msg); + + 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(cmd_sk, &msg, 0); + if (ret < 0) { + error("Receiving command response failed, aborting :%s", + strerror(errno)); + pthread_mutex_unlock(&cmd_sk_mutex); + exit(EXIT_FAILURE); + } + + pthread_mutex_unlock(&cmd_sk_mutex); + + if (ret < (ssize_t) sizeof(hal_msg)) { + error("Too small response received(%zd bytes), aborting", ret); + exit(EXIT_FAILURE); + } + + if (ret != (ssize_t) (sizeof(hal_msg) + hal_msg.len)) { + error("Malformed response received(%zd bytes), aborting", ret); + exit(EXIT_FAILURE); + } + + if (hal_msg.opcode != opcode && hal_msg.opcode != HAL_MSG_OP_ERROR) { + error("Invalid opcode received (%u vs %u), aborting", + hal_msg.opcode, opcode); + exit(EXIT_FAILURE); + } + + if (hal_msg.opcode == HAL_MSG_OP_ERROR) { + struct hal_msg_rsp_error *err = rsp; + return -err->status; + } + + /* 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; + } + } + } + + return hal_msg.len; +} diff --git a/android/hal-ipc.h b/android/hal-ipc.h index 2f7166881..3834e7d20 100644 --- a/android/hal-ipc.h +++ b/android/hal-ipc.h @@ -17,3 +17,6 @@ bool hal_ipc_init(void); void hal_ipc_cleanup(void); + +int hal_ipc_cmd(uint8_t service_id, uint8_t opcode, uint16_t len, void *param, + size_t rsp_len, void *rsp, int *fd); -- 2.11.0