blob: e3ad9327bab7e1a5d9645d353962a536340669ca [file] [log] [blame]
#include <string.h>
#include <dlfcn.h>
#include <hardware/hardware.h>
#include <hardware/audio.h>
#include <pthread.h>
#include <cutils/log.h>
#include "audio_if.h"
#define AUDIO_HAL_LIB "libaudio_hal.so"
static pthread_mutex_t if_mutex = PTHREAD_MUTEX_INITIALIZER;
static int if_ref_cnt;
static audio_hw_device_t *hw_dev;
static int load(const char *id,
const char *path,
struct hw_module_t **pHmi)
{
int status = -EINVAL;
void *handle = NULL;
struct hw_module_t *hmi = NULL;
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
handle = dlopen(path, RTLD_NOW);
if (!handle) {
const char *err_str = dlerror();
ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
status = -EINVAL;
goto done;
}
/* Get the address of the struct hal_module_info. */
hmi = (struct hw_module_t *)dlsym(handle, sym);
if (!hmi) {
ALOGE("load: couldn't find symbol %s", sym);
status = -EINVAL;
goto done;
}
/* Check that the id matches */
if (strcmp(id, hmi->id) != 0) {
ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
status = -EINVAL;
goto done;
}
hmi->dso = handle;
/* success */
status = 0;
done:
if (status != 0) {
hmi = NULL;
if (handle != NULL) {
dlclose(handle);
handle = NULL;
}
} else {
ALOGE("loaded HAL id=%s path=%s hmi=%p handle=%p",
id, path, *pHmi, handle);
}
*pHmi = hmi;
return status;
}
int audio_hw_load_interface(audio_hw_device_t **dev)
{
int r;
struct hw_module_t *pHmi = NULL;
pthread_mutex_lock(&if_mutex);
if (if_ref_cnt) {
*dev = hw_dev;
if_ref_cnt++;
pthread_mutex_unlock(&if_mutex);
return 0;
}
r = load(AUDIO_HARDWARE_MODULE_ID, AUDIO_HAL_LIB, &pHmi);
if (r) {
ALOGE("audio_hw_load_module couldn't load audio_hal module");
goto out;
}
r = pHmi->methods->open(pHmi, AUDIO_HARDWARE_INTERFACE,
(struct hw_device_t**)dev);
if (r) {
ALOGE("audio_hw_load_module couldn't open device");
goto out;
}
if_ref_cnt++;
hw_dev = *dev;
pthread_mutex_unlock(&if_mutex);
return 0;
out:
*dev = NULL;
pthread_mutex_unlock(&if_mutex);
return r;
}
void audio_hw_unload_interface(audio_hw_device_t *dev)
{
struct hw_module_t *pHmi = dev->common.module;
int ret = 0;
pthread_mutex_lock(&if_mutex);
if (if_ref_cnt >= 1)
if_ref_cnt--;
if (if_ref_cnt == 0 && pHmi) {
ret = dlclose(pHmi->dso);
if (ret)
ALOGE("%s, failed to close audio_hal module:%s\n", __FUNCTION__, dlerror());
pHmi = NULL;
hw_dev = NULL;
}
pthread_mutex_unlock(&if_mutex);
}