| /* |
| * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * Changes from Qualcomm Innovation Center are provided under the following license: |
| * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. |
| * SPDX-License-Identifier: BSD-3-Clause-Clear |
| */ |
| |
| #define LOG_TAG "sthal_SoundTriggerDevice" |
| |
| #define ATRACE_TAG (ATRACE_TAG_AUDIO | ATRACE_TAG_HAL) |
| |
| #define LOG_NDEBUG 0 |
| /*#define VERY_VERY_VERBOSE_LOGGING*/ |
| #ifdef VERY_VERY_VERBOSE_LOGGING |
| #define ALOGVV ALOGV |
| #else |
| #define ALOGVV(a...) do { } while (0) |
| #endif |
| |
| #include "SoundTriggerDevice.h" |
| |
| #include <log/log.h> |
| #include <cutils/atomic.h> |
| #include <utils/Trace.h> |
| |
| #include "PalApi.h" |
| |
| #define XSTR(x) STR(x) |
| #define STR(x) #x |
| |
| static int stdev_ref_cnt = 0; |
| static struct sound_trigger_properties_extended_1_3 hw_properties_extended; |
| |
| /* |
| * Current API version used by STHAL. Queried by AHAL |
| * for compatibility check with STHAL |
| */ |
| extern "C" const unsigned int sthal_prop_api_version = |
| STHAL_PROP_API_CURRENT_VERSION; |
| |
| std::shared_ptr<SoundTriggerDevice> SoundTriggerDevice::stdev_ = nullptr; |
| std::shared_ptr<sound_trigger_hw_device> SoundTriggerDevice::device_ = nullptr; |
| |
| #ifdef LSM_HIDL_ENABLED |
| #include <hidl/HidlTransportSupport.h> |
| #include <hidl/LegacySupport.h> |
| |
| #include <lsm_server_wrapper.h> |
| |
| #include <vendor/qti/hardware/ListenSoundModel/1.0/IListenSoundModel.h> |
| using vendor::qti::hardware::ListenSoundModel::V1_0::IListenSoundModel; |
| using vendor::qti::hardware::ListenSoundModel::V1_0::implementation::ListenSoundModel; |
| using android::hardware::defaultPassthroughServiceImplementation; |
| using android::sp; |
| using namespace android::hardware; |
| using android::OK; |
| #endif |
| |
| static int stdev_close(hw_device_t *device) |
| { |
| int status = 0; |
| std::shared_ptr<SoundTriggerDevice> st_device = nullptr; |
| |
| ALOGD("%s: Enter", __func__); |
| ATRACE_BEGIN("sthal: stdev_close"); |
| |
| st_device = SoundTriggerDevice::GetInstance(device); |
| if (!st_device) { |
| ALOGE("%s: error, GetInstance failed", __func__); |
| status = -EINVAL; |
| goto exit; |
| } |
| |
| if (--stdev_ref_cnt != 0) { |
| goto exit; |
| } |
| |
| exit: |
| ATRACE_END(); |
| ALOGD("%s: Exit, status = %d", __func__, status); |
| |
| return status; |
| } |
| |
| static int stdev_get_properties(const struct sound_trigger_hw_device *dev, |
| struct sound_trigger_properties *properties) |
| { |
| int status = 0; |
| std::shared_ptr<SoundTriggerDevice> st_device = nullptr; |
| struct pal_st_properties *qstp = nullptr; |
| size_t size = 0; |
| |
| ALOGV("%s: Enter", __func__); |
| |
| if (!dev || !properties) { |
| ALOGE("%s: invalid inputs", __func__); |
| return -EINVAL; |
| } |
| |
| st_device = SoundTriggerDevice::GetInstance(dev); |
| if (!st_device) { |
| ALOGE("%s: error, GetInstance failed", __func__); |
| return -EINVAL; |
| } |
| |
| status = pal_get_param(PAL_PARAM_ID_GET_SOUND_TRIGGER_PROPERTIES, |
| (void **)&qstp, &size, nullptr); |
| if (status || !qstp || size < sizeof(struct pal_st_properties)) { |
| ALOGE("%s: query properties from pal failed, status %d", |
| __func__, status); |
| goto exit; |
| } |
| |
| memcpy(properties, qstp, sizeof(struct sound_trigger_properties)); |
| |
| ALOGVV("%s version=0x%x recognition_modes=%d, capture_transition=%d, " |
| "concurrent_capture=%d", __func__, properties->version, |
| properties->recognition_modes, properties->capture_transition, |
| properties->concurrent_capture); |
| hw_properties_extended.header.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_0; |
| |
| exit: |
| if (qstp) |
| free(qstp); |
| |
| ALOGV("%s: Exit, status = %d", __func__, status); |
| return status; |
| } |
| |
| static int stdev_load_sound_model(const struct sound_trigger_hw_device *dev, |
| struct sound_trigger_sound_model *sound_model, |
| sound_model_callback_t callback __unused, |
| void *cookie __unused, |
| sound_model_handle_t *handle) |
| { |
| int status = 0; |
| std::shared_ptr<SoundTriggerDevice> st_device = nullptr; |
| SoundTriggerSession* st_session = nullptr; |
| |
| ALOGV("%s: Enter", __func__); |
| ATRACE_BEGIN("sthal: stdev_load_sound_model"); |
| |
| st_device = SoundTriggerDevice::GetInstance(dev); |
| if (!st_device) { |
| ALOGE("%s: error, GetInstance failed", __func__); |
| status = -EINVAL; |
| goto exit; |
| } |
| |
| // assign sound model handle |
| *handle = android_atomic_inc(&st_device->session_id_); |
| |
| // create sound trigger stream |
| st_session = new SoundTriggerSession(*handle, st_device->ahal_callback_); |
| status = st_device->RegisterSession(st_session); |
| if (status) { |
| ALOGE("%s: error, failed to register session", __func__); |
| goto exit; |
| } |
| |
| // load sound model |
| status = st_session->LoadSoundModel(sound_model); |
| if (status) |
| ALOGE("%s: error, Failed to load sound model, status = %d", |
| __func__, status); |
| |
| exit: |
| ATRACE_END(); |
| ALOGV("%s: Exit, status = %d", __func__, status); |
| |
| return status; |
| } |
| |
| static int stdev_unload_sound_model(const struct sound_trigger_hw_device *dev, |
| sound_model_handle_t handle) |
| { |
| int status = 0; |
| std::shared_ptr<SoundTriggerDevice> st_device = nullptr; |
| SoundTriggerSession* st_session = nullptr; |
| |
| ALOGV("%s: Enter", __func__); |
| ATRACE_BEGIN("sthal: stdev_unload_sound_model"); |
| |
| st_device = SoundTriggerDevice::GetInstance(dev); |
| if (!st_device) { |
| ALOGE("%s: error, GetInstance failed", __func__); |
| status = -EINVAL; |
| goto exit; |
| } |
| |
| st_session = st_device->GetSession(handle); |
| if (!st_session) { |
| ALOGE("%s: error, failed to get st stream by handle %d", |
| __func__, handle); |
| status = -EINVAL; |
| goto exit; |
| } |
| |
| // deregister sound model handle |
| status = st_session->UnloadSoundModel(); |
| if (status) { |
| ALOGE("%s: error, failed to unload sound model, status = %d", |
| __func__, status); |
| goto exit; |
| } |
| |
| status = st_device->DeregisterSession(st_session); |
| if (status) { |
| ALOGE("%s: error, failed to deregister session", __func__); |
| goto exit; |
| } |
| |
| exit: |
| ATRACE_END(); |
| ALOGV("%s: Exit, status = %d", __func__, status); |
| |
| return status; |
| } |
| |
| static int stdev_start_recognition |
| ( |
| const struct sound_trigger_hw_device *dev, |
| sound_model_handle_t sound_model_handle, |
| const struct sound_trigger_recognition_config *config, |
| recognition_callback_t callback, |
| void *cookie) |
| { |
| int status = 0; |
| std::shared_ptr<SoundTriggerDevice> st_device = nullptr; |
| SoundTriggerSession* st_session = nullptr; |
| |
| ALOGV("%s: Enter", __func__); |
| ATRACE_BEGIN("sthal: stdev_start_recognition"); |
| |
| st_device = SoundTriggerDevice::GetInstance(dev); |
| if (!st_device) { |
| ALOGE("%s: error, GetInstance failed", __func__); |
| status = -EINVAL; |
| goto exit; |
| } |
| |
| st_session = st_device->GetSession(sound_model_handle); |
| if (!st_session) { |
| ALOGE("%s: error, failed to get st stream by handle %d", |
| __func__, sound_model_handle); |
| status = -EINVAL; |
| goto exit; |
| } |
| |
| status = st_session->StartRecognition(config, |
| callback, cookie, hw_properties_extended.header.version); |
| if (status) { |
| ALOGE("%s: error, failed to start recognition, status = %d", |
| __func__, status); |
| goto exit; |
| } |
| |
| exit: |
| ATRACE_END(); |
| ALOGV("%s: Exit, status = %d", __func__, status); |
| |
| return status; |
| } |
| |
| static int stdev_stop_recognition(const struct sound_trigger_hw_device *dev, |
| sound_model_handle_t sound_model_handle) |
| { |
| int status = 0; |
| std::shared_ptr<SoundTriggerDevice> st_device = nullptr; |
| SoundTriggerSession* st_session = nullptr; |
| |
| ALOGV("%s: Enter", __func__); |
| ATRACE_BEGIN("sthal: stdev_stop_recognition"); |
| |
| st_device = SoundTriggerDevice::GetInstance(dev); |
| if (!st_device) { |
| ALOGE("%s: error, GetInstance failed", __func__); |
| status = -EINVAL; |
| goto exit; |
| } |
| |
| st_session = st_device->GetSession(sound_model_handle); |
| if (!st_session) { |
| ALOGE("%s: error, Failed to get st stream by handle %d", |
| __func__, sound_model_handle); |
| status = -EINVAL; |
| goto exit; |
| } |
| |
| // deregister sound model handle |
| status = st_session->StopRecognition(); |
| if (status) { |
| ALOGE("%s: error, failed to stop recognition, status = %d", |
| __func__, status); |
| goto exit; |
| } |
| |
| exit: |
| ATRACE_END(); |
| ALOGV("%s: Exit, status = %d", __func__, status); |
| |
| return status; |
| } |
| |
| #ifdef ST_SUPPORT_GET_MODEL_STATE |
| static int stdev_get_model_state(const struct sound_trigger_hw_device *dev, |
| sound_model_handle_t handle) |
| { |
| return 0; |
| } |
| #endif |
| |
| static int stdev_start_recognition_extended |
| ( |
| const struct sound_trigger_hw_device *dev, |
| sound_model_handle_t sound_model_handle, |
| const struct sound_trigger_recognition_config_header *config, |
| recognition_callback_t callback, |
| void *cookie |
| ) |
| { |
| return stdev_start_recognition(dev, sound_model_handle, |
| &((struct sound_trigger_recognition_config_extended_1_3 *)config)->base, |
| callback, cookie); |
| } |
| |
| static int stdev_stop_all_recognitions(const struct sound_trigger_hw_device* dev __unused) |
| { |
| ALOGV("%s: unsupported API", __func__); |
| return -ENOSYS; |
| } |
| |
| static int stdev_get_parameter(const struct sound_trigger_hw_device *dev __unused, |
| sound_model_handle_t sound_model_handle __unused, |
| sound_trigger_model_parameter_t model_param __unused, int32_t* value __unused) |
| { |
| ALOGV("%s: unsupported API", __func__); |
| return -EINVAL; |
| } |
| |
| static int stdev_set_parameter(const struct sound_trigger_hw_device *dev __unused, |
| sound_model_handle_t sound_model_handle __unused, |
| sound_trigger_model_parameter_t model_param __unused, int32_t value __unused) |
| { |
| ALOGV("%s: unsupported API", __func__); |
| return -EINVAL; |
| } |
| |
| static int stdev_query_parameter(const struct sound_trigger_hw_device *dev __unused, |
| sound_model_handle_t sound_model_handle __unused, |
| sound_trigger_model_parameter_t model_param __unused, |
| sound_trigger_model_parameter_range_t* param_range) |
| { |
| if (param_range) |
| param_range->is_supported = false; |
| return 0; |
| } |
| |
| static const struct sound_trigger_properties_header* |
| stdev_get_properties_extended(const struct sound_trigger_hw_device *dev) |
| { |
| int status = 0; |
| struct sound_trigger_properties_header *prop_hdr = NULL; |
| std::shared_ptr<SoundTriggerDevice> st_device = nullptr; |
| SoundTriggerSession* st_session = nullptr; |
| |
| ALOGV("%s: Enter", __func__); |
| if (!dev) { |
| ALOGW("%s: invalid sound_trigger_hw_device received", __func__); |
| return nullptr; |
| } |
| |
| st_device = SoundTriggerDevice::GetInstance(dev); |
| if (!st_device) { |
| ALOGE("%s: error, GetInstance failed", __func__); |
| return nullptr; |
| } |
| |
| prop_hdr = (struct sound_trigger_properties_header *)&hw_properties_extended; |
| status = stdev_get_properties(dev, &hw_properties_extended.base); |
| if (status) { |
| ALOGW("%s: Failed to initialize the stdev properties", __func__); |
| return nullptr; |
| } |
| hw_properties_extended.header.size = sizeof(struct sound_trigger_properties_extended_1_3); |
| hw_properties_extended.audio_capabilities = 0; |
| hw_properties_extended.header.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_3; |
| |
| // TODO: update first stage module version after confirm with Venky |
| st_session = new SoundTriggerSession(0, nullptr); |
| status = st_session->GetModuleVersion(hw_properties_extended.supported_model_arch); |
| delete st_session; |
| if (status) { |
| ALOGE("%s: Failed to get module version, status = %d", __func__, status); |
| } |
| |
| return prop_hdr; |
| } |
| |
| std::shared_ptr<SoundTriggerDevice> SoundTriggerDevice::GetInstance() |
| { |
| if (!stdev_) { |
| stdev_ = std::shared_ptr<SoundTriggerDevice> |
| (new SoundTriggerDevice()); |
| device_ = std::shared_ptr<sound_trigger_hw_device> |
| (new sound_trigger_hw_device()); |
| } |
| |
| return stdev_; |
| } |
| |
| std::shared_ptr<SoundTriggerDevice> SoundTriggerDevice::GetInstance( |
| const hw_device_t *device) |
| { |
| if (device == (hw_device_t *)&(device_.get()->common)) |
| return SoundTriggerDevice::stdev_; |
| else |
| return nullptr; |
| } |
| |
| std::shared_ptr<SoundTriggerDevice> SoundTriggerDevice::GetInstance( |
| const struct sound_trigger_hw_device *st_device) |
| { |
| if (st_device == (struct sound_trigger_hw_device *)device_.get()) |
| return SoundTriggerDevice::stdev_; |
| else |
| return nullptr; |
| } |
| |
| int SoundTriggerDevice::Init(hw_device_t **device, const hw_module_t *module) |
| { |
| int status = 0; |
| |
| ALOGD("%s: Enter", __func__); |
| |
| if (stdev_ref_cnt != 0) { |
| *device = &device_->common; |
| stdev_ref_cnt++; |
| ALOGD("%s: returning existing stdev instance, exit", __func__); |
| return status; |
| } |
| |
| #ifdef LSM_HIDL_ENABLED |
| /* Register LSM Lib HIDL service */ |
| ALOGD("%s: Register LSM HIDL service", __func__); |
| sp<IListenSoundModel> service = new ListenSoundModel(); |
| if(android::OK != service->registerAsService()) |
| ALOGW("Could not register LSM HIDL service"); |
| #endif |
| |
| // load audio hal |
| status = LoadAudioHal(); |
| if (status) { |
| ALOGE("%s: failed to load audio hal, status = %d", __func__, status); |
| goto exit; |
| } |
| |
| // platform init |
| status = PlatformInit(); |
| if (status) { |
| ALOGE("%s: failed to do platform init, status = %d", __func__, status); |
| goto exit; |
| } |
| |
| // assign function pointers |
| device_->common.tag = HARDWARE_DEVICE_TAG; |
| device_->common.version = SOUND_TRIGGER_DEVICE_API_VERSION_1_3; |
| device_->common.module = (struct hw_module_t *)module; |
| device_->common.close = stdev_close; |
| device_->get_properties = stdev_get_properties; |
| device_->load_sound_model = stdev_load_sound_model; |
| device_->unload_sound_model = stdev_unload_sound_model; |
| device_->start_recognition = stdev_start_recognition; |
| device_->stop_recognition = stdev_stop_recognition; |
| device_->get_properties_extended = stdev_get_properties_extended; |
| device_->start_recognition_extended = stdev_start_recognition_extended; |
| device_->stop_all_recognitions = stdev_stop_all_recognitions; |
| device_->get_parameter = stdev_get_parameter; |
| device_->set_parameter = stdev_set_parameter; |
| device_->query_parameter = stdev_query_parameter; |
| #ifdef ST_SUPPORT_GET_MODEL_STATE |
| device_->get_model_state = stdev_get_model_state; |
| #endif |
| *device = &device_->common; |
| |
| hw_properties_extended.header.size = |
| sizeof(struct sound_trigger_properties_extended_1_3); |
| hw_properties_extended.audio_capabilities = 0; |
| hw_properties_extended.header.version = |
| SOUND_TRIGGER_DEVICE_API_VERSION_1_3; |
| |
| available_devices_ = AUDIO_DEVICE_IN_BUILTIN_MIC; |
| session_id_ = 1; |
| stdev_ref_cnt++; |
| |
| exit: |
| ALOGV("%s: Exit, status = %d", __func__, status); |
| |
| return status; |
| } |
| |
| int SoundTriggerDevice::LoadAudioHal() |
| { |
| int status = 0; |
| char audio_hal_lib[100]; |
| void *apiVersion = nullptr; |
| audio_extn_hidl_init initAudioExtn = nullptr; |
| |
| ALOGD("%s: Enter", __func__); |
| |
| snprintf(audio_hal_lib, sizeof(audio_hal_lib), "%s/%s.%s.so", |
| AUDIO_HAL_LIBRARY_PATH1, AUDIO_HAL_NAME_PREFIX, |
| XSTR(SOUND_TRIGGER_PLATFORM)); |
| if (access(audio_hal_lib, R_OK)) { |
| snprintf(audio_hal_lib, sizeof(audio_hal_lib), "%s/%s.%s.so", |
| AUDIO_HAL_LIBRARY_PATH2, AUDIO_HAL_NAME_PREFIX, |
| XSTR(SOUND_TRIGGER_PLATFORM)); |
| if (access(audio_hal_lib, R_OK)) { |
| ALOGE("%s: ERROR. %s not found", __func__, audio_hal_lib); |
| status = -ENOENT; |
| goto error; |
| } |
| } |
| |
| ahal_handle_ = dlopen(audio_hal_lib, RTLD_NOW); |
| if (!ahal_handle_) { |
| ALOGE("%s: ERROR. %s", __func__, dlerror()); |
| status = -ENODEV; |
| goto error; |
| } |
| |
| ahal_callback_ = (audio_hw_call_back_t)dlsym(ahal_handle_, |
| "audio_hw_call_back"); |
| if (!ahal_callback_) { |
| ALOGE("%s: error, failed to get symbol for audio_hw_call_back", |
| __func__); |
| status = -ENODEV; |
| goto error; |
| } |
| apiVersion = dlsym(ahal_handle_, "sthal_prop_api_version"); |
| if (!apiVersion) { |
| sthal_prop_api_version_ = 0; |
| status = 0; // passthru for backward compability |
| } else { |
| sthal_prop_api_version_ = *(int*)apiVersion; |
| if (MAJOR_VERSION(sthal_prop_api_version_) != |
| MAJOR_VERSION(sthal_prop_api_version)) { |
| ALOGE("%s: Incompatible API versions sthal:0x%x != ahal:0x%x", |
| __func__, STHAL_PROP_API_CURRENT_VERSION, |
| sthal_prop_api_version_); |
| goto error; |
| } |
| ALOGD("%s: ahal is using API version 0x%04x", __func__, |
| sthal_prop_api_version_); |
| } |
| |
| initAudioExtn = (audio_extn_hidl_init)dlsym(ahal_handle_, "check_init_audio_extension"); |
| if (!initAudioExtn) { |
| ALOGW("%s: error, failed to get symbol for initAudioExtn", |
| __func__); |
| } else { |
| status = initAudioExtn(); |
| if (status) { |
| ALOGE("%s: error, failed to init audio extn", __func__); |
| goto error; |
| } |
| } |
| return status; |
| |
| error: |
| if (ahal_handle_) { |
| dlclose(ahal_handle_); |
| ahal_handle_ = nullptr; |
| } |
| ALOGV("%s: Exit, status = %d", __func__, status); |
| |
| return status; |
| } |
| |
| int SoundTriggerDevice::PlatformInit() |
| { |
| int status = 0; |
| // load platform related config |
| conc_capture_supported_ = false; |
| |
| return status; |
| } |
| |
| SoundTriggerSession* SoundTriggerDevice::GetSession(sound_model_handle_t handle) |
| { |
| for (int i = 0; i < session_list_.size(); i++) { |
| if (handle == session_list_[i]->GetSoundModelHandle()) |
| return session_list_[i]; |
| } |
| |
| return nullptr; |
| } |
| |
| int SoundTriggerDevice::RegisterSession(SoundTriggerSession* session) |
| { |
| int status = 0; |
| |
| mutex_.lock(); |
| session_list_.push_back(session); |
| mutex_.unlock(); |
| |
| return status; |
| } |
| |
| int SoundTriggerDevice::DeregisterSession(SoundTriggerSession* session) |
| { |
| int status = 0; |
| SoundTriggerSession *st_session = nullptr; |
| |
| mutex_.lock(); |
| typename std::vector<SoundTriggerSession *>::iterator iter = |
| std::find(session_list_.begin(), session_list_.end(), session); |
| if (iter != session_list_.end()) { |
| st_session = *iter; |
| if (!st_session) { |
| delete st_session; |
| st_session = nullptr; |
| } |
| session_list_.erase(iter); |
| } else { |
| status = -ENOENT; |
| ALOGE("%s: session found in session list", __func__); |
| } |
| mutex_.unlock(); |
| |
| return status; |
| } |
| |
| static int stdev_open(const hw_module_t* module, const char* name, |
| hw_device_t** device) |
| { |
| int status = 0; |
| std::shared_ptr<SoundTriggerDevice> st_device = nullptr; |
| |
| ALOGD("%s: Enter", __func__); |
| ATRACE_BEGIN("sthal: stdev_open"); |
| |
| if (strcmp(name, SOUND_TRIGGER_HARDWARE_INTERFACE) != 0) { |
| ALOGE("%s: ERROR. wrong interface", __func__); |
| status = -EINVAL; |
| goto exit; |
| } |
| |
| st_device = SoundTriggerDevice::GetInstance(); |
| if (!st_device) { |
| ALOGE("%s: error, GetInstance failed", __func__); |
| goto exit; |
| } |
| |
| status = st_device->Init(device, module); |
| if (status || (*device == nullptr)) |
| ALOGE("%s: error, audio device init failed, ret(%d), *device(%p)", |
| __func__, status, *device); |
| |
| exit: |
| ATRACE_END(); |
| ALOGV("%s: Exit, status = %d", __func__, status); |
| |
| return status; |
| } |
| |
| static struct hw_module_methods_t hal_module_methods = { |
| .open = stdev_open, |
| }; |
| |
| struct sound_trigger_module HAL_MODULE_INFO_SYM = { |
| .common = { |
| .tag = HARDWARE_MODULE_TAG, |
| .module_api_version = SOUND_TRIGGER_MODULE_API_VERSION_1_0, |
| .hal_api_version = HARDWARE_HAL_API_VERSION, |
| .id = SOUND_TRIGGER_HARDWARE_MODULE_ID, |
| .name = "Sound trigger HAL", |
| .author = "QUALCOMM Technologies, Inc", |
| .methods = &hal_module_methods, |
| }, |
| }; |