hal: update adsp handler to handle multiple events
Update adsp handler logic to handle multiple events from ADSP
Change-Id: Icd2bf5ef7649e5781a8c3aae7aa0e3a42a43f11d
diff --git a/hal/audio_extn/adsp_hdlr.c b/hal/audio_extn/adsp_hdlr.c
index 08313a6..436da96 100644
--- a/hal/audio_extn/adsp_hdlr.c
+++ b/hal/audio_extn/adsp_hdlr.c
@@ -45,6 +45,8 @@
#include <cutils/log.h>
#include <cutils/sched_policy.h>
#include <system/thread_defs.h>
+#include <sound/asound.h>
+#include <linux/msm_audio.h>
#include "audio_hw.h"
#include "audio_defs.h"
@@ -57,40 +59,29 @@
#define MIXER_MAX_BYTE_LENGTH 512
-struct adsp_hdlr_inst {
- bool binit;
- struct mixer *mixer;
-};
-
-enum {
- EVENT_CMD_EXIT, /* event thread exit command loop*/
- EVENT_CMD_WAIT, /* event thread wait on mixer control */
- EVENT_CMD_GET /* event thread get param data from mixer */
-};
-
-struct event_cmd {
- struct listnode list;
- int opcode;
-};
-
-enum {
- ADSP_HDLR_STREAM_STATE_OPENED = 0,
- ADSP_HDLR_STREAM_STATE_EVENT_REGISTERED,
- ADSP_HDLR_STREAM_STATE_EVENT_DEREGISTERED,
- ADSP_HDLR_STREAM_STATE_CLOSED
-};
-
-static struct adsp_hdlr_inst *adsp_hdlr_inst = NULL;
-
-static void *event_wait_thread_loop(void *context);
-static void *event_callback_thread_loop(void *context);
-
struct adsp_hdlr_stream_data {
struct adsp_hdlr_stream_cfg config;
stream_callback_t client_callback;
void *client_cookie;
- int state;
+};
+struct adsp_hdlr_event_info {
+ struct listnode list;
+ void *stream_handle;
+ char mixer_ctl_name[MIXER_PATH_MAX_LENGTH];
+ char cb_mixer_ctl_name[MIXER_PATH_MAX_LENGTH];
+ adsp_event_callback_t cb;
+ void *cookie;
+ int event_type;
+};
+
+struct adsp_hdlr_inst {
+ struct listnode event_list;
+ bool binit;
+ struct mixer *mixer;
+ pthread_mutex_t event_list_lock;
+
+ struct listnode list;
pthread_cond_t event_wait_cond;
pthread_t event_wait_thread;
struct listnode event_wait_cmd_list;
@@ -104,7 +95,24 @@
bool event_callback_thread_active;
};
-static int send_cmd_event_wait_thread(struct adsp_hdlr_stream_data *stream_data, int opcode)
+enum {
+ EVENT_CMD_EXIT, /* event thread exit command loop*/
+ EVENT_CMD_WAIT, /* event thread wait on mixer control */
+ EVENT_CMD_GET /* event thread get param data from mixer */
+};
+
+struct event_cmd {
+ struct listnode list;
+ int opcode;
+ char cb_mixer_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+};
+
+static struct adsp_hdlr_inst *adsp_hdlr_inst = NULL;
+
+static void *event_wait_thread_loop(void *context);
+static void *event_callback_thread_loop(void *context);
+
+static int send_cmd_event_wait_thread(struct adsp_hdlr_inst *adsp_hdlr_inst, int opcode)
{
struct event_cmd *cmd = calloc(1, sizeof(*cmd));
@@ -117,16 +125,16 @@
cmd->opcode = opcode;
- pthread_mutex_lock(&stream_data->event_wait_lock);
- list_add_tail(&stream_data->event_wait_cmd_list, &cmd->list);
- pthread_cond_signal(&stream_data->event_wait_cond);
- pthread_mutex_unlock(&stream_data->event_wait_lock);
+ pthread_mutex_lock(&adsp_hdlr_inst->event_wait_lock);
+ list_add_tail(&adsp_hdlr_inst->event_wait_cmd_list, &cmd->list);
+ pthread_cond_signal(&adsp_hdlr_inst->event_wait_cond);
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_wait_lock);
return 0;
}
-static int send_cmd_event_callback_thread(struct adsp_hdlr_stream_data *stream_data,
- int opcode)
+static int send_cmd_event_callback_thread(struct adsp_hdlr_inst *adsp_hdlr_inst,
+ int opcode, char *mixer_ctl_name)
{
struct event_cmd *cmd = calloc(1, sizeof(*cmd));
@@ -135,66 +143,68 @@
return -ENOMEM;
}
- ALOGVV("%s %d", __func__, opcode);
+ ALOGVV("%s opcode %d, name = %s", __func__, opcode, mixer_ctl_name);
cmd->opcode = opcode;
+ if (mixer_ctl_name)
+ strlcpy(cmd->cb_mixer_ctl_name, mixer_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
- pthread_mutex_lock(&stream_data->event_callback_lock);
- list_add_tail(&stream_data->event_callback_cmd_list, &cmd->list);
- pthread_cond_signal(&stream_data->event_callback_cond);
- pthread_mutex_unlock(&stream_data->event_callback_lock);
+ pthread_mutex_lock(&adsp_hdlr_inst->event_callback_lock);
+ list_add_tail(&adsp_hdlr_inst->event_callback_cmd_list, &cmd->list);
+ pthread_cond_signal(&adsp_hdlr_inst->event_callback_cond);
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_callback_lock);
return 0;
}
-static void create_event_wait_thread(struct adsp_hdlr_stream_data *stream_data)
+static void create_event_wait_thread(struct adsp_hdlr_inst *adsp_hdlr_inst)
{
- pthread_cond_init(&stream_data->event_wait_cond,
+ pthread_cond_init(&adsp_hdlr_inst->event_wait_cond,
(const pthread_condattr_t *) NULL);
- list_init(&stream_data->event_wait_cmd_list);
- pthread_create(&stream_data->event_wait_thread, (const pthread_attr_t *) NULL,
- event_wait_thread_loop, stream_data);
- stream_data->event_wait_thread_active = true;
+ list_init(&adsp_hdlr_inst->event_wait_cmd_list);
+ pthread_create(&adsp_hdlr_inst->event_wait_thread, (const pthread_attr_t *) NULL,
+ event_wait_thread_loop, adsp_hdlr_inst);
+ adsp_hdlr_inst->event_wait_thread_active = true;
}
-static void create_event_callback_thread(struct adsp_hdlr_stream_data *stream_data)
+static void create_event_callback_thread(struct adsp_hdlr_inst *adsp_hdlr_inst)
{
- pthread_cond_init(&stream_data->event_callback_cond,
+ pthread_cond_init(&adsp_hdlr_inst->event_callback_cond,
(const pthread_condattr_t *) NULL);
- list_init(&stream_data->event_callback_cmd_list);
- pthread_create(&stream_data->event_callback_thread, (const pthread_attr_t *) NULL,
- event_callback_thread_loop, stream_data);
- stream_data->event_callback_thread_active = true;
+ list_init(&adsp_hdlr_inst->event_callback_cmd_list);
+ pthread_create(&adsp_hdlr_inst->event_callback_thread, (const pthread_attr_t *) NULL,
+ event_callback_thread_loop, adsp_hdlr_inst);
+ adsp_hdlr_inst->event_callback_thread_active = true;
}
-static void destroy_event_wait_thread(struct adsp_hdlr_stream_data *stream_data)
+static void destroy_event_wait_thread(struct adsp_hdlr_inst *adsp_hdlr_inst)
{
- send_cmd_event_wait_thread(stream_data, EVENT_CMD_EXIT);
- pthread_join(stream_data->event_wait_thread, (void **) NULL);
+ send_cmd_event_wait_thread(adsp_hdlr_inst, EVENT_CMD_EXIT);
+ pthread_join(adsp_hdlr_inst->event_wait_thread, (void **) NULL);
- pthread_mutex_lock(&stream_data->event_wait_lock);
- pthread_cond_destroy(&stream_data->event_wait_cond);
- stream_data->event_wait_thread_active = false;
- pthread_mutex_unlock(&stream_data->event_wait_lock);
+ pthread_mutex_lock(&adsp_hdlr_inst->event_wait_lock);
+ pthread_cond_destroy(&adsp_hdlr_inst->event_wait_cond);
+ adsp_hdlr_inst->event_wait_thread_active = false;
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_wait_lock);
}
-static void destroy_event_callback_thread(struct adsp_hdlr_stream_data *stream_data)
+static void destroy_event_callback_thread(struct adsp_hdlr_inst *adsp_hdlr_inst)
{
- send_cmd_event_callback_thread(stream_data, EVENT_CMD_EXIT);
- pthread_join(stream_data->event_callback_thread, (void **) NULL);
+ send_cmd_event_callback_thread(adsp_hdlr_inst, EVENT_CMD_EXIT, NULL);
+ pthread_join(adsp_hdlr_inst->event_callback_thread, (void **) NULL);
- pthread_mutex_lock(&stream_data->event_callback_lock);
- pthread_cond_destroy(&stream_data->event_callback_cond);
- stream_data->event_callback_thread_active = false;
- pthread_mutex_unlock(&stream_data->event_callback_lock);
+ pthread_mutex_lock(&adsp_hdlr_inst->event_callback_lock);
+ pthread_cond_destroy(&adsp_hdlr_inst->event_callback_cond);
+ adsp_hdlr_inst->event_callback_thread_active = false;
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_callback_lock);
}
-static void destroy_event_threads(struct adsp_hdlr_stream_data *stream_data)
+static void destroy_event_threads(struct adsp_hdlr_inst *adsp_hdlr_inst)
{
- if (stream_data->event_wait_thread_active)
- destroy_event_wait_thread(stream_data);
- if (stream_data->event_callback_thread_active)
- destroy_event_callback_thread(stream_data);
+ if (adsp_hdlr_inst->event_wait_thread_active)
+ destroy_event_wait_thread(adsp_hdlr_inst);
+ if (adsp_hdlr_inst->event_callback_thread_active)
+ destroy_event_callback_thread(adsp_hdlr_inst);
}
static void *event_wait_thread_loop(void *context)
@@ -202,53 +212,35 @@
int ret = 0;
int opcode = 0;
bool wait = false;
- struct adsp_hdlr_stream_data *stream_data =
- (struct adsp_hdlr_stream_data *) context;
- struct adsp_hdlr_stream_cfg *config = &stream_data->config;
- char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
- struct mixer_ctl *ctl = NULL;
+ struct adsp_hdlr_inst *adsp_hdlr_inst =
+ (struct adsp_hdlr_inst *) context;
struct event_cmd *cmd;
- struct listnode *node;
+ struct listnode *node, *tempnode;
+ struct snd_ctl_event mixer_event = {0};
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
set_sched_policy(0, SP_BACKGROUND);
prctl(PR_SET_NAME, (unsigned long)"Event Wait", 0, 0, 0);
- ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
- "ADSP Stream Callback Event %d", config->pcm_device_id);
- if (ret < 0) {
- ALOGE("%s: snprintf failed",__func__);
- ret = -EINVAL;
- goto done;
- }
-
- ctl = mixer_get_ctl_by_name(adsp_hdlr_inst->mixer, mixer_ctl_name);
- if (!ctl) {
- ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
- mixer_ctl_name);
- ret = -EINVAL;
- goto done;
- }
-
ret = mixer_subscribe_events(adsp_hdlr_inst->mixer, 1);
if (ret < 0) {
- ALOGE("%s: Could not subscribe for mixer cmd - %s, ret %d",
- __func__, mixer_ctl_name, ret);
+ ALOGE("%s: Could not subscribe for mixer events, ret %d",
+ __func__, ret);
goto done;
}
- pthread_mutex_lock(&stream_data->event_wait_lock);
+ pthread_mutex_lock(&adsp_hdlr_inst->event_wait_lock);
while (1) {
- if (list_empty(&stream_data->event_wait_cmd_list) && !wait) {
+ if (list_empty(&adsp_hdlr_inst->event_wait_cmd_list) && !wait) {
ALOGVV("%s SLEEPING", __func__);
- pthread_cond_wait(&stream_data->event_wait_cond, &stream_data->event_wait_lock);
+ pthread_cond_wait(&adsp_hdlr_inst->event_wait_cond, &adsp_hdlr_inst->event_wait_lock);
ALOGVV("%s RUNNING", __func__);
}
/* execute command if available */
- if (!list_empty(&stream_data->event_wait_cmd_list)) {
- node = list_head(&stream_data->event_wait_cmd_list);
+ if (!list_empty(&adsp_hdlr_inst->event_wait_cmd_list)) {
+ node = list_head(&adsp_hdlr_inst->event_wait_cmd_list);
list_remove(node);
- pthread_mutex_unlock(&stream_data->event_wait_lock);
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_wait_lock);
cmd = node_to_item(node, struct event_cmd, list);
opcode = cmd->opcode;
/* wait if no command avialable */
@@ -265,30 +257,20 @@
goto thread_exit;
case EVENT_CMD_WAIT:
ret = mixer_wait_event(adsp_hdlr_inst->mixer, WAIT_EVENT_POLL_TIMEOUT);
- if (ret < 0)
- ALOGE("%s: mixer_wait_event err! mixer %s, ret = %d",
- __func__, mixer_ctl_name, ret);
- else if (ret > 0) {
- send_cmd_event_callback_thread(stream_data, EVENT_CMD_GET);
-
- /* Resubscribe to clear flag checked by mixer_wait_event */
- ret = mixer_subscribe_events(adsp_hdlr_inst->mixer, 0);
- if (ret < 0) {
- ALOGE("%s: Could not unsubscribe for mixer cmd - %s, ret %d",
- __func__, mixer_ctl_name, ret);
- goto done;
- }
- ret = mixer_subscribe_events(adsp_hdlr_inst->mixer, 1);
- if (ret < 0) {
- ALOGE("%s: Could not unsubscribe for mixer cmd - %s, ret %d",
- __func__, mixer_ctl_name, ret);
- goto done;
- }
+ ALOGVV("%s: mixer_wait_event unblocked!, ret = %d", __func__, ret);
+ if (ret < 0) {
+ ALOGE("%s: mixer_wait_event err!, ret = %d", __func__, ret);
+ } else if (ret > 0) {
+ ret = mixer_read(adsp_hdlr_inst->mixer, &mixer_event);
+ if (ret >= 0)
+ send_cmd_event_callback_thread(adsp_hdlr_inst, EVENT_CMD_GET, mixer_event.data.elem.id.name);
+ else
+ ALOGE("%s: mixer_read failed, ret = %d", __func__, ret);
}
/* Once wait command has been sent continue to wait for
events unless something else is in the command que */
wait = true;
- break;
+ break;
default:
ALOGE("%s unknown command received: %d", __func__, opcode);
break;
@@ -300,12 +282,18 @@
}
}
thread_exit:
- pthread_mutex_lock(&stream_data->event_wait_lock);
- list_for_each(node, &stream_data->event_wait_cmd_list) {
+ ret = mixer_subscribe_events(adsp_hdlr_inst->mixer, 0);
+ if (ret < 0) {
+ ALOGE("%s: Could not un-subscribe for mixer events, ret %d",
+ __func__, ret);
+ goto done;
+ }
+ pthread_mutex_lock(&adsp_hdlr_inst->event_wait_lock);
+ list_for_each_safe(node, tempnode, &adsp_hdlr_inst->event_wait_cmd_list) {
list_remove(node);
free(node);
}
- pthread_mutex_unlock(&stream_data->event_wait_lock);
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_wait_lock);
done:
return NULL;
}
@@ -314,47 +302,32 @@
{
int ret = 0;
size_t count = 0;
- struct adsp_hdlr_stream_data *stream_data =
- (struct adsp_hdlr_stream_data *)context;
- struct adsp_hdlr_stream_cfg *config = &stream_data->config;
- char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+ struct adsp_hdlr_inst *adsp_hdlr_inst =
+ (struct adsp_hdlr_inst *)context;
struct mixer_ctl *ctl = NULL;
uint8_t param[MAX_EVENT_PAYLOAD] = {0};
struct event_cmd *cmd;
- struct listnode *node;
+ struct listnode *node, *tempnode;
+ struct adsp_hdlr_event_info *event_info;
+ bool param_avail = false;
+ struct msm_adsp_event_data *received_evt;
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
set_sched_policy(0, SP_BACKGROUND);
prctl(PR_SET_NAME, (unsigned long)"Event Callback", 0, 0, 0);
- ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
- "ADSP Stream Callback Event %d", config->pcm_device_id);
- if (ret < 0) {
- ALOGE("%s: snprintf failed",__func__);
- ret = -EINVAL;
- goto done;
- }
-
- ctl = mixer_get_ctl_by_name(adsp_hdlr_inst->mixer, mixer_ctl_name);
- if (!ctl) {
- ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
- mixer_ctl_name);
- ret = -EINVAL;
- goto done;
- }
-
- pthread_mutex_lock(&stream_data->event_callback_lock);
+ pthread_mutex_lock(&adsp_hdlr_inst->event_callback_lock);
while (1) {
- if (list_empty(&stream_data->event_callback_cmd_list)) {
+ if (list_empty(&adsp_hdlr_inst->event_callback_cmd_list)) {
ALOGVV("%s SLEEPING", __func__);
- pthread_cond_wait(&stream_data->event_callback_cond,
- &stream_data->event_callback_lock);
+ pthread_cond_wait(&adsp_hdlr_inst->event_callback_cond,
+ &adsp_hdlr_inst->event_callback_lock);
ALOGVV("%s RUNNING", __func__);
continue;
}
- node = list_head(&stream_data->event_callback_cmd_list);
+ node = list_head(&adsp_hdlr_inst->event_callback_cmd_list);
list_remove(node);
- pthread_mutex_unlock(&stream_data->event_callback_lock);
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_callback_lock);
cmd = node_to_item(node, struct event_cmd, list);
ALOGVV("%s command received: %d", __func__, cmd->opcode);
@@ -363,30 +336,60 @@
free(cmd);
goto thread_exit;
case EVENT_CMD_GET:
- mixer_ctl_update(ctl);
-
- count = mixer_ctl_get_num_values(ctl);
- if ((count > MAX_EVENT_PAYLOAD) || (count <= 0)) {
- ALOGE("%s mixer - %s, count is %d",
- __func__, mixer_ctl_name, count);
- break;
+ param_avail = false;
+ pthread_mutex_lock(&adsp_hdlr_inst->event_list_lock);
+ /* Find the mixer control for which event is triggered */
+ list_for_each(node, &adsp_hdlr_inst->event_list) {
+ event_info = node_to_item(node, struct adsp_hdlr_event_info, list);
+ ALOGVV("%s: cmd mixer name: %s, event list mixer name: %s", __func__,
+ cmd->cb_mixer_ctl_name, event_info->cb_mixer_ctl_name);
+ if (!strcmp(cmd->cb_mixer_ctl_name, event_info->cb_mixer_ctl_name)) {
+ if (!param_avail) {
+ ctl = mixer_get_ctl_by_name(adsp_hdlr_inst->mixer, cmd->cb_mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
+ cmd->cb_mixer_ctl_name);
+ break;
+ }
+ mixer_ctl_update(ctl);
+ count = mixer_ctl_get_num_values(ctl);
+ if ((count > MAX_EVENT_PAYLOAD) || (count <= 0)) {
+ ALOGE("%s: count is %d greater than allowed for %s mixer cmd",
+ __func__, count, cmd->cb_mixer_ctl_name);
+ break;
+ }
+ ret = mixer_ctl_get_array(ctl, param, count);
+ if (ret < 0) {
+ ALOGE("%s: mixer_ctl_get_array failed! mixer - %s, ret = %d",
+ __func__, cmd->cb_mixer_ctl_name, ret);
+ break;
+ }
+ param_avail = true;
+ received_evt = (struct msm_adsp_event_data *)param;
+ ALOGD("%s: event type = %d", __func__, received_evt->event_type);
+ }
+ /* Call appropriate event type client callback */
+ if (param_avail && event_info->event_type == received_evt->event_type) {
+ struct adsp_hdlr_stream_data *stream_data = event_info->stream_handle;
+ if (event_info->cb != NULL) {
+ ALOGVV("%s: calling event callback function", __func__);
+ event_info->cb(event_info->stream_handle,
+ received_evt->payload,
+ event_info->cookie);
+ } else if (stream_data->client_callback != NULL) {
+ ALOGVV("%s: sending client callback event %d", __func__,
+ AUDIO_EXTN_STREAM_CBK_EVENT_ADSP);
+ stream_data->client_callback((stream_callback_event_t)
+ AUDIO_EXTN_STREAM_CBK_EVENT_ADSP,
+ received_evt,
+ stream_data->client_cookie);
+ }
+ break;
+ }
+ }
}
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_list_lock);
- ret = mixer_ctl_get_array(ctl, param, count);
- if (ret < 0) {
- ALOGE("%s: mixer_ctl_get_array failed! mixer - %s, ret = %d",
- __func__, mixer_ctl_name, ret);
- break;
- }
-
- if (stream_data->client_callback != NULL) {
- ALOGVV("%s: sending client callback event %d", __func__,
- AUDIO_EXTN_STREAM_CBK_EVENT_ADSP);
- stream_data->client_callback((stream_callback_event_t)
- AUDIO_EXTN_STREAM_CBK_EVENT_ADSP,
- param,
- stream_data->client_cookie);
- }
break;
default:
ALOGE("%s unknown command received: %d", __func__, cmd->opcode);
@@ -395,39 +398,101 @@
free(cmd);
}
thread_exit:
- pthread_mutex_lock(&stream_data->event_callback_lock);
- list_for_each(node, &stream_data->event_callback_cmd_list) {
+ pthread_mutex_lock(&adsp_hdlr_inst->event_callback_lock);
+ list_for_each_safe(node, tempnode, &adsp_hdlr_inst->event_callback_cmd_list) {
list_remove(node);
free(node);
}
- pthread_mutex_unlock(&stream_data->event_callback_lock);
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_callback_lock);
done:
return NULL;
}
-static int adsp_hdlr_stream_deregister_event(
- struct adsp_hdlr_stream_data *stream_data)
+int audio_extn_adsp_hdlr_stream_deregister_event(void *handle, void *data)
{
- destroy_event_threads((struct adsp_hdlr_stream_data *)stream_data);
- stream_data->state = ADSP_HDLR_STREAM_STATE_EVENT_DEREGISTERED;
+ struct listnode *node, *tempnode;
+ struct adsp_hdlr_stream_data *stream_data = (struct adsp_hdlr_stream_data *)handle;
+ struct adsp_hdlr_event_info *event_info;
+ struct audio_adsp_event *param = (struct audio_adsp_event *)data;
+
+ if (!handle) {
+ ALOGE("%s: Invalid handle", __func__);
+ return -EINVAL;
+ }
+
+ pthread_mutex_lock(&adsp_hdlr_inst->event_list_lock);
+ if (list_empty(&adsp_hdlr_inst->event_list)) {
+ ALOGD("%s: event list is empty", __func__);
+ return 0;
+ }
+ list_for_each_safe(node, tempnode, &adsp_hdlr_inst->event_list) {
+ event_info = node_to_item(node, struct adsp_hdlr_event_info, list);
+ if (param && event_info->stream_handle == stream_data) {
+ /* if the type of event is avaliable to dereg then dereg only that event */
+ if (event_info->event_type == param->event_type) {
+ ALOGD("%s: Deregister event type = %d", __func__, event_info->event_type);
+ list_remove(node);
+ free(event_info);
+ }
+ } else if (event_info->stream_handle == stream_data) {
+ /* Dereg all the events related to that stream */
+ ALOGD("%s: Deregister all stream events", __func__);
+ list_remove(node);
+ free(event_info);
+ }
+ }
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_list_lock);
+
+ if (list_empty(&adsp_hdlr_inst->event_list)) {
+ ALOGD("%s: Closing event threads", __func__);
+ destroy_event_threads(adsp_hdlr_inst);
+ pthread_mutex_destroy(&adsp_hdlr_inst->event_wait_lock);
+ pthread_mutex_destroy(&adsp_hdlr_inst->event_callback_lock);
+ pthread_mutex_destroy(&adsp_hdlr_inst->event_list_lock);
+ }
+
return 0;
}
-static int adsp_hdlr_stream_register_event(
- struct adsp_hdlr_stream_data *stream_data,
- struct audio_adsp_event *param)
+int audio_extn_adsp_hdlr_stream_register_event(void *handle, void *data,
+ adsp_event_callback_t cb,
+ void *cookie)
{
int ret = 0;
char mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+ char cb_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
struct mixer_ctl *ctl = NULL;
uint8_t payload[AUDIO_MAX_ADSP_STREAM_CMD_PAYLOAD_LEN] = {0};
+ struct adsp_hdlr_stream_data *stream_data = (struct adsp_hdlr_stream_data *)handle;
struct adsp_hdlr_stream_cfg *config = &stream_data->config;
+ struct adsp_hdlr_event_info *event_info;
+ struct audio_adsp_event *param = (struct audio_adsp_event *)data;
+
+ if (!param || !handle) {
+ ret = -EINVAL;
+ ALOGE("%s: Invalid input arguments", __func__);
+ goto done;
+ }
/* check if param size exceeds max size supported by mixer */
if (param->payload_length > AUDIO_MAX_ADSP_STREAM_CMD_PAYLOAD_LEN) {
ALOGE("%s: Invalid payload_length %d",__func__, param->payload_length);
return -EINVAL;
}
+ ret = snprintf(cb_mixer_ctl_name, sizeof(cb_mixer_ctl_name),
+ "ADSP Stream Callback Event %d", config->pcm_device_id);
+ if (ret < 0) {
+ ALOGE("%s: snprintf failed",__func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ ctl = mixer_get_ctl_by_name(adsp_hdlr_inst->mixer, cb_mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
+ cb_mixer_ctl_name);
+ ret = -EINVAL;
+ goto done;
+ }
ret = snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
"ADSP Stream Cmd %d", config->pcm_device_id);
@@ -444,36 +509,63 @@
ret = -EINVAL;
goto done;
}
+ ALOGD("%s: event = %d, payload_length %d", __func__, param->event_type, param->payload_length);
- ALOGD("%s: payload_length %d",__func__, param->payload_length);
-
- /*copy payload size and param */
- memcpy(payload, ¶m->payload_length,
+ /* copy event_type, payload size and payload */
+ memcpy(payload, ¶m->event_type,
+ sizeof(param->event_type));
+ memcpy(payload + sizeof(param->event_type), ¶m->payload_length,
sizeof(param->payload_length));
- memcpy(payload + sizeof(param->payload_length),
+ memcpy(payload + sizeof(param->event_type) + sizeof(param->payload_length),
param->payload, param->payload_length);
- ret = mixer_ctl_set_array(ctl, payload,
- sizeof(param->payload_length) + param->payload_length);
+ ret = mixer_ctl_set_array(ctl, payload, (sizeof(param->event_type) +
+ sizeof(param->payload_length) + param->payload_length));
if (ret < 0) {
ALOGE("%s: Could not set ctl for mixer cmd - %s, ret %d", __func__,
mixer_ctl_name, ret);
goto done;
}
- pthread_mutex_lock(&stream_data->event_wait_lock);
- if (!stream_data->event_wait_thread_active)
- create_event_wait_thread(stream_data);
- pthread_mutex_unlock(&stream_data->event_wait_lock);
+ if (list_empty(&adsp_hdlr_inst->event_list)) {
+ pthread_mutex_init(&adsp_hdlr_inst->event_wait_lock,
+ (const pthread_mutexattr_t *) NULL);
+ pthread_mutex_init(&adsp_hdlr_inst->event_callback_lock,
+ (const pthread_mutexattr_t *) NULL);
+ pthread_mutex_init(&adsp_hdlr_inst->event_list_lock,
+ (const pthread_mutexattr_t *) NULL);
- pthread_mutex_lock(&stream_data->event_callback_lock);
- if (!stream_data->event_callback_thread_active)
- create_event_callback_thread(stream_data);
- pthread_mutex_unlock(&stream_data->event_callback_lock);
+ /* create event threads during first event registration */
+ pthread_mutex_lock(&adsp_hdlr_inst->event_wait_lock);
+ if (!adsp_hdlr_inst->event_wait_thread_active)
+ create_event_wait_thread(adsp_hdlr_inst);
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_wait_lock);
- send_cmd_event_wait_thread(stream_data, EVENT_CMD_WAIT);
- stream_data->state = ADSP_HDLR_STREAM_STATE_EVENT_REGISTERED;
+ pthread_mutex_lock(&adsp_hdlr_inst->event_callback_lock);
+ if (!adsp_hdlr_inst->event_callback_thread_active)
+ create_event_callback_thread(adsp_hdlr_inst);
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_callback_lock);
+
+ send_cmd_event_wait_thread(adsp_hdlr_inst, EVENT_CMD_WAIT);
+ }
+ event_info = (struct adsp_hdlr_event_info *) calloc(1,
+ sizeof(struct adsp_hdlr_event_info));
+ if (event_info == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ event_info->event_type = param->event_type;
+ event_info->cb = cb;
+ event_info->cookie = cookie;
+ event_info->stream_handle = stream_data;
+ strlcpy(event_info->mixer_ctl_name, mixer_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+ strlcpy(event_info->cb_mixer_ctl_name, cb_mixer_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+ pthread_mutex_lock(&adsp_hdlr_inst->event_list_lock);
+ list_add_tail(&adsp_hdlr_inst->event_list, &event_info->list);
+ ALOGD("%s: event_info type %d added from the list", __func__, event_info->event_type);
+ pthread_mutex_unlock(&adsp_hdlr_inst->event_list_lock);
+
done:
- return ret;
+ return ret;
}
int audio_extn_adsp_hdlr_stream_set_param(void *handle,
@@ -481,28 +573,21 @@
void *param)
{
int ret = 0;
- struct adsp_hdlr_stream_data *stream_data;
if (handle == NULL) {
ALOGE("%s: Invalid handle",__func__);
return -EINVAL;
}
- stream_data = (struct adsp_hdlr_stream_data *)handle;
switch (cmd) {
case ADSP_HDLR_STREAM_CMD_REGISTER_EVENT :
- if (!param) {
- ret = -EINVAL;
- ALOGE("%s: Invalid handle",__func__);
- break;
- }
- ret = adsp_hdlr_stream_register_event(stream_data, param);
+ ret = audio_extn_adsp_hdlr_stream_register_event(handle, param, NULL, NULL);
if (ret)
ALOGE("%s:adsp_hdlr_stream_register_event failed error %d",
__func__, ret);
break;
case ADSP_HDLR_STREAM_CMD_DEREGISTER_EVENT:
- ret = adsp_hdlr_stream_deregister_event(stream_data);
+ ret = audio_extn_adsp_hdlr_stream_deregister_event(handle, param);
if (ret)
ALOGE("%s:adsp_hdlr_stream_deregister_event failed error %d",
__func__, ret);
@@ -546,15 +631,10 @@
ret = -EINVAL;
} else {
stream_data = (struct adsp_hdlr_stream_data *)handle;
- if (stream_data->state == ADSP_HDLR_STREAM_STATE_EVENT_REGISTERED) {
- ret = adsp_hdlr_stream_deregister_event(stream_data);
- if (ret)
- ALOGE("%s:adsp_hdlr_stream_deregister_event failed error %d",
- __func__, ret);
- }
- stream_data->state = ADSP_HDLR_STREAM_STATE_CLOSED;
- pthread_mutex_destroy(&stream_data->event_wait_lock);
- pthread_mutex_destroy(&stream_data->event_wait_lock);
+ ret = audio_extn_adsp_hdlr_stream_deregister_event(stream_data, NULL);
+ if (ret)
+ ALOGE("%s:adsp_hdlr_stream_deregister_event failed error %d",
+ __func__, ret);
free(stream_data);
stream_data = NULL;
}
@@ -588,15 +668,9 @@
if (stream_data == NULL) {
ret = -ENOMEM;
}
-
stream_data->config = *config;
- pthread_mutex_init(&stream_data->event_wait_lock,
- (const pthread_mutexattr_t *) NULL);
- pthread_mutex_init(&stream_data->event_callback_lock,
- (const pthread_mutexattr_t *) NULL);
- stream_data->state = ADSP_HDLR_STREAM_STATE_OPENED;
-
*handle = (void **)stream_data;
+
return ret;
}
@@ -614,14 +688,15 @@
return 0;
}
adsp_hdlr_inst = (struct adsp_hdlr_inst *)calloc(1,
- sizeof(struct adsp_hdlr_inst *));
+ sizeof(struct adsp_hdlr_inst));
if (!adsp_hdlr_inst) {
ALOGE("%s: calloc failed for adsp_hdlr_inst", __func__);
return -EINVAL;
}
adsp_hdlr_inst->mixer = mixer;
+ list_init(&adsp_hdlr_inst->event_list);
- return 0;
+ return 0;
}
int audio_extn_adsp_hdlr_deinit(void)
diff --git a/hal/audio_extn/adsp_hdlr.h b/hal/audio_extn/adsp_hdlr.h
index 7499917..b265e42 100644
--- a/hal/audio_extn/adsp_hdlr.h
+++ b/hal/audio_extn/adsp_hdlr.h
@@ -42,6 +42,9 @@
};
#ifdef AUDIO_EXTN_ADSP_HDLR_ENABLED
+
+typedef int (*adsp_event_callback_t)(void *handle, void *payload, void *cookie);
+
int audio_extn_adsp_hdlr_init(struct mixer *mixer);
int audio_extn_adsp_hdlr_deinit(void);
int audio_extn_adsp_hdlr_stream_open(void **handle,
@@ -53,6 +56,9 @@
int audio_extn_adsp_hdlr_stream_set_param(void *handle,
adsp_hdlr_cmd_t cmd,
void *param);
+int audio_extn_adsp_hdlr_stream_register_event(void *handle,
+ void *param, adsp_event_callback_t cb, void *cookie);
+int audio_extn_adsp_hdlr_stream_deregister_event(void *handle, void *param);
#else
#define audio_extn_adsp_hdlr_init(mixer) (0)
#define audio_extn_adsp_hdlr_deinit() (0)
@@ -60,6 +66,8 @@
#define audio_extn_adsp_hdlr_stream_close(handle) (0)
#define audio_extn_adsp_hdlr_stream_set_callback(handle, callback, cookie) (0)
#define audio_extn_adsp_hdlr_stream_set_param(handle, cmd, param) (0)
+#define audio_extn_adsp_hdlr_stream_register_event(stream_data, param, cb) (0)
+#define audio_extn_adsp_hdlr_stream_deregister_event(handle, param) (0)
#endif
#endif
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index ea84b75..c3201b4 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -199,12 +199,18 @@
*/
} audio_extn_callback_id;
-#define AUDIO_MAX_ADSP_STREAM_CMD_PAYLOAD_LEN 508
+#define AUDIO_MAX_ADSP_STREAM_CMD_PAYLOAD_LEN 504
+
+typedef enum {
+ AUDIO_STREAM_PP_EVENT = 0,
+ AUDIO_STREAM_ENCDEC_EVENT = 1,
+} audio_event_id;
/* payload format for HAL parameter
* AUDIO_EXTN_PARAM_ADSP_STREAM_CMD
*/
struct audio_adsp_event {
+ audio_event_id event_type; /* type of the event */
uint32_t payload_length; /* length in bytes of the payload */
void *payload; /* the actual payload */
};
diff --git a/qahw_api/inc/qahw_defs.h b/qahw_api/inc/qahw_defs.h
index 3900676..8438d6e 100644
--- a/qahw_api/inc/qahw_defs.h
+++ b/qahw_api/inc/qahw_defs.h
@@ -293,10 +293,16 @@
#define QAHW_MAX_ADSP_STREAM_CMD_PAYLOAD_LEN 512
+typedef enum {
+ QAHW_STREAM_PP_EVENT = 0,
+ QAHW_STREAM_ENCDEC_EVENT = 1,
+} qahw_event_id;
+
/* payload format for HAL parameter
* QAHW_PARAM_ADSP_STREAM_CMD
*/
struct qahw_adsp_event {
+ qahw_event_id event_type; /* type of the event */
uint32_t payload_length; /* length in bytes of the payload */
void *payload; /* the actual payload */
};
diff --git a/qahw_api/test/qahw_playback_test.c b/qahw_api/test/qahw_playback_test.c
index 96f0c5f..2c7864a 100644
--- a/qahw_api/test/qahw_playback_test.c
+++ b/qahw_api/test/qahw_playback_test.c
@@ -422,8 +422,9 @@
case QAHW_STREAM_CBK_EVENT_ADSP:
fprintf(log_file, "stream %d: received event - QAHW_STREAM_CBK_EVENT_ADSP\n", params->stream_index);
if (payload != NULL) {
- fprintf(log_file, "param_length %d\n", payload[0]);
- for (i=1; i* sizeof(uint32_t) <= payload[0]; i++)
+ fprintf(log_file, "event_type %d\n", payload[0]);
+ fprintf(log_file, "param_length %d\n", payload[1]);
+ for (i=2; i* sizeof(uint32_t) <= payload[1]; i++)
fprintf(log_file, "param[%d] = 0x%x\n", i, payload[i]);
}
break;
@@ -1239,6 +1240,7 @@
event_payload.module_id = 0x10940;
event_payload.config_mask = 1;
+ payload.adsp_event_params.event_type = QAHW_STREAM_PP_EVENT;
payload.adsp_event_params.payload_length = sizeof(event_payload);
payload.adsp_event_params.payload = &event_payload;