static int set_anc(sqlite3_stmt *stmt)
{
    const unsigned int NR_OF_ANC_FIR_COEFFS = 15;
    const unsigned int NR_OF_ANC_IIR_COEFFS = 24;
    long anc_fir_coefficients[NR_OF_ANC_FIR_COEFFS];
    long anc_iir_coefficients[NR_OF_ANC_IIR_COEFFS];
    unsigned int i;
    int value, ret;

    // 15 signed 16bit FIR-coefficients
    ALOG_INFO("%s: Configuring ANC FIR-coefficients.\n", __func__);
    for (i = 0; i < NR_OF_ANC_FIR_COEFFS; i++)
        anc_fir_coefficients[i] = sqlite3_column_int(stmt, i + 5);
    ret = audio_hal_alsa_set_control_values("ANC FIR Coefficients", anc_fir_coefficients);
    if (ret < 0) {
        ALOG_ERR("%s: ERROR: Unable to set ANC FIR-coefficients!\n", __func__);
        return ret;
    }

    // 1bit double delay + 8 signed 5bit internal IIR shift + 20 signed 24bit IIR-coefficients
    ALOG_INFO("%s: Configuring ANC IIR-shift and IIR-coefficients.\n", __func__);
    for (i = 0; i < NR_OF_ANC_IIR_COEFFS; i++)
        anc_iir_coefficients[i] = sqlite3_column_int(stmt, i + 20);
    ret = audio_hal_alsa_set_control_values("ANC IIR Coefficients", anc_iir_coefficients);
    if (ret < 0) {
        ALOG_ERR("%s: ERROR: Unable to set ANC IIR-coefficients!\n", __func__);
        return ret;
    }

    // 3 signed 5bit external shift parameters and 1 unsigned 16bit warp delay parameter
    ALOG_INFO("%s: Configuring ANC Warp and Shifts.\n", __func__);
    for (i = 0; i < 4; i++) {
        value = sqlite3_column_int(stmt, i + 1);
        if (i == 0)
            ret = audio_hal_alsa_set_control("ANC Warp Delay Shift", 0, value);
        else if (i == 1)
            ret = audio_hal_alsa_set_control("ANC FIR Output Shift", 0, value);
        else if (i == 2)
            ret = audio_hal_alsa_set_control("ANC IIR Output Shift", 0, value);
        else if (i == 3)
            ret = audio_hal_alsa_set_control("ANC Warp Delay", 0, value);
        if (ret < 0) {
            ALOG_ERR("%s: ERROR: Unable to set ANC IIR Warp or Shift!\n", __func__);
            return ret;
        }
    }

    // configure FIR-/IIR-coefficients into ab8500 ANC block
    ret = audio_hal_alsa_set_control("ANC Status", 0, 1);
    if (ret < 0) {
        ALOG_ERR("%s: ERROR: Unable to apply ANC FIR+IIR-coefficients!\n", __func__);
        return ret;
    }

    ret = audio_hal_alsa_set_control("ANC Playback Switch", 0, 1);
    if (ret < 0)
        ALOG_ERR("%s: ERROR: Unable to enable ANC! (ret = %d)\n", __func__, ret);

    return ret;
}
static void AppendD2D(sqlite3* db_p, hw_handler_dev_to_dev_next_fp_t dev_next_d2d_fp)
{
    int rc = SQLITE_OK;
    sqlite3_stmt *stmt = NULL;
    const char* src_name = NULL;
    const char* dst_name = NULL;
    char *command = NULL;
    const unsigned char* data = NULL;
    int ret;

    ALOG_INFO("%s ENTER", __func__);

    command = malloc(1024 * sizeof(char));
    while(dev_next_d2d_fp(&src_name, &dst_name) == 0) {
        UpdateD2DFlags(src_name, dst_name);
        memset(command, 0, 1024);
        sprintf(command, "SELECT Data FROM HW_Settings_Data_D2D WHERE Idx=(\
                    SELECT Idx_Data FROM HW_Settings_Combo_D2D WHERE (Codec = '%s') AND (Src='%s') AND (Dst='%s'))",
                codec_name_ab8500_p, src_name, dst_name);

        rc = sqlite3_prepare_v2(db_p, command, -1, &stmt, NULL);
        if (rc != SQLITE_OK) {
            ALOG_ERR("%s: ERROR: Unable to prepare SQL-statement!", __func__);
            goto cleanup;
        }

        if (sqlite3_step(stmt) != SQLITE_ROW)
            goto cleanup;

        data = sqlite3_column_text(stmt, 0);
        if (data == NULL) {
            ALOG_ERR("%s: ERROR: Data not found !\n", __func__);
            goto cleanup;
        }
        ret = audio_hal_alsa_set_controls_cfg((const char*)data);
        if (ret < 0) {
            ALOG_ERR("%s: ERROR: Failed to write HW-settings! ste_adm_hw_handler_alsa_set_controls returned %d.", __func__, ret);
            goto cleanup;
        }
        ALOG_INFO("%s: found Match src: %s, dst :%s \n %s\n", __func__, src_name, dst_name, data);
    }

cleanup:
    if (command != NULL) free(command);
    if (stmt != NULL) {
        sqlite3_finalize(stmt);
        stmt = NULL;
    }
}
int ste_adm_hw_handler_init_u8500(const char* card_name)
{
    int ret = 0;
    int ret_func = STE_ADM_RES_ALSA_ERROR;

    ALOG_INFO("%s: Enter (card_name = '%s').", __func__, card_name);

    card_name_p = card_name;

    ret = audio_hal_alsa_open_controls(card_name_p);
    if (ret < 0) {
        ALOG_ERR("%s: ERROR: Unable to open ALSA-card '%s'!\n", __func__, card_name_p);
        goto cleanup;
    }

    if (mic_type == MICROPHONE_TYPE_ANALOG) {
        audio_hal_alsa_set_control("Mic 1A Regulator", 0, mic_1a_regulator);
        audio_hal_alsa_set_control("Mic 1B Regulator", 0, mic_1b_regulator);
        audio_hal_alsa_set_control("Mic 2 Regulator", 0, mic_2_regulator);
    }

    ret = audio_hal_alsa_set_control("Master Clock Select", 0, 1); // Default -> ULPCLK
    if (ret < 0) {
        ALOG_ERR("%s: ERROR: Unable to set master clock select! (ret = %d)\n", __func__, ret);
        goto cleanup;
    }

    ret_func = STE_ADM_RES_OK;

cleanup:
    audio_hal_alsa_close_controls();
    return ret_func;
}
ste_adm_res_t il_tool_create_component(il_comp_t* comp_hp, const char* name, const char* dbg_type)
{
    ADM_ASSERT(comp_hp != NULL);
    ADM_ASSERT(name    != NULL);

    // GetHandle sometimes takes time
    SRV_DBG_ASSERT_IS_WORKER_THREAD;

    adm_il_appdata_t* app_data_p = malloc(sizeof(*app_data_p));
    if (!app_data_p) {
        ALOG_ERR("Out of memory allocating %d bytes\n", sizeof(*app_data_p));
        return STE_ADM_RES_ERR_MALLOC;
    }

    memset(app_data_p, 0, sizeof(*app_data_p));
    il_tool_io_init(app_data_p->bufinfo);
    *comp_hp = app_data_p;
    app_data_p->callback_state.last_error = OMX_ErrorNone;


    app_data_p->callback_state.event_callback_fp = NULL;


    int retval = pthread_mutex_init(&app_data_p->mutex, NULL);
    if (retval != 0) {
        ALOG_ERR("pthread_mutex_init failed, errno = %d\n", errno);
        free(app_data_p);
        return STE_ADM_RES_ERR_MALLOC;
    }

    ste_adm_res_t res = il_tool_log_CreateComponent(name, app_data_p);
    if (res != STE_ADM_RES_OK)
    {
        pthread_mutex_destroy(&app_data_p->mutex);
        free(app_data_p);
        ALOG_ERR("Error: il_tool_log_CreateComponent returned %d\n", res);
        return res;
    }

    if (ste_adm_debug_omx_trace_enabled(name, dbg_type)) {
        ALOG_INFO("Enabling OST traces for '%s', '%s'\n", name, dbg_type);
        OMX_HANDLETYPE omx_h = il_tool_raw_handle(*comp_hp);

        // Enable all OSI traces except buffer traces (they are very verbose)
        il_tool_enable_trace(*comp_hp, (OMX_U16) 65535 & ~OSI_TRACE_BUFFER, (OMX_U32) (omx_h));
    }

    res = adm_adaptions_setup_comp(*comp_hp, name);


    if (res != STE_ADM_RES_OK) {
        ALOG_ERR("adm_adaptions_setup_comp failed for %s, err=%X\n", name, res);
        il_tool_log_FreeHandle(*comp_hp);
        pthread_mutex_destroy(&app_data_p->mutex);
        free(app_data_p);
        *comp_hp = NULL;
        return res;
    }
    return STE_ADM_RES_OK;
}
static int usb_init( hw_ext_module_t * hw_module){
    if(hw_module->data==NULL)
        hw_module->data=(void*)malloc(sizeof(struct usb_internal_data_s));

    ALOG_INFO("Initialization of ANM interface with USB external HAL");
    memset(hw_module->data,0,sizeof(struct usb_internal_data_s));
    ((struct usb_internal_data_s*)(hw_module->data))->state=IO_CLOSED;
    return 0;
}
int usb_get_capabilities(hw_ext_module_t * hw_module){
    ALOG_INFO("GetUSBCapabilities()");
    strcpy(hw_module->name,"USB");
    hw_module->ops=&s_usb_ops;
    hw_module->supported_input=0;
    hw_module->supported_output=AUDIO_DEVICE_OUT_ALL_USB;
    hw_module->data=NULL;
    return 0;
}
static ste_audio_output_descriptor_t * usb_open_output(hw_ext_module_t * hw_module,audio_devices_t   device,audio_io_handle_t * pHandle){
    audio_policy_anm *apm=hw_module->apm;
    struct usb_internal_data_s * usb_info = (struct usb_internal_data_s *)hw_module->data;

    if(usb_info==NULL)
        return NULL;

    *pHandle=-1;
    switch(usb_info->state) {
        case IO_CLOSED: break;
        case IO_DISCONNECTED:
        case IO_CONNECTED:
        case IO_OPENED:
            ALOG_INFO("usb_open_output : Output already opened ( current state : %s)",usb_state2str[usb_info->state]);
            return (&(usb_info->output_desc));
            break;
        default:
            ALOG_INFO("usb_open_output : unknown state");
    }

    ALOG_INFO("usb_open_output()" );
    ste_audio_output_descriptor_t *output_desc = &(usb_info->output_desc);
    init_audio_output_descriptor(output_desc);
    output_desc->mDevice = device;
    output_desc->mStrategyRefCount = 1;
    output_desc->mStrategy = STRATEGY_MEDIA;

    usb_info->output_handle = apm->mp_client_interface->open_output(apm->mService,
                                            &output_desc->mDevice,
                                            &output_desc->mSamplingRate,
                                            &output_desc->mFormat,
                                            &output_desc->mChannels,
                                            &output_desc->mLatency,
                                            output_desc->mFlags);

    if (usb_info->output_handle) {
        output_desc->output_id=usb_info->output_handle;
        ALOG_INFO("USB opened [IO Handle : %d]",usb_info->output_handle);
        usb_info->state=IO_OPENED;
        *pHandle=usb_info->output_handle;
        return output_desc;
    }
    return NULL;
}
/**
 *  Creates an OMX component and sets all platform specific configurations required.
 *  Those can be overridden in database if required.
 */
ste_adm_res_t adm_adaptions_setup_comp(
    il_comp_t      Handle,
    const char* cComponentName)
{
    ste_adm_res_t res = STE_ADM_RES_OK;
    ALOG_INFO("Enter adm_platform_adaptions_setup\n");

#ifdef STE_ADM_WORKAROUND_STANDARD_TUNNELING
    force_standard_tunneling(Handle);
#endif

    // TODO: Find out what components that require the echo reference port to be disabled
    if (strcmp(cComponentName, "OMX.ST.AFM.NOKIA_AV_SINK") == 0 ||
        strcmp(cComponentName, "OMX.ST.AFM.IHF") == 0 ||
        strcmp(cComponentName, "OMX.ST.AFM.EARPIECE") == 0 ||
        strcmp(cComponentName, "OMX.ST.AFM.BT_MONO_SINK") == 0 ||
        strcmp(cComponentName, "OMX.ST.AFM.alsasink") == 0 )
    {
        // echo reference is port 1
        if (il_tool_change_port_state(Handle, 1, 0, 0)) {
            ALOG_ERR("Failed to disable clock port on component %s\n", cComponentName);
            return STE_ADM_RES_IL_UNKNOWN_ERROR; // TODO: Error from il_tool_change_port_state? Use IL_ macros?
        }
    }
#ifdef ADM_SUPPORT_RC_FILTER
    if (strcmp(cComponentName, "OMX.ST.AFM.NOKIA_AV_SINK") == 0 ||
        strcmp(cComponentName, "OMX.ST.AFM.IHF") == 0 ||
        strcmp(cComponentName, "OMX.ST.AFM.EARPIECE") == 0 ||
        strcmp(cComponentName, "OMX.ST.AFM.NOKIA_AV_SOURCE") == 0 ||
        strcmp(cComponentName, "OMX.ST.AFM.MULTI_MIC") == 0 ||
        strcmp(cComponentName, "OMX.ST.AFM.FM_SINK") == 0 ||
        strcmp(cComponentName, "OMX.ST.AFM.FM_SOURCE") == 0)
    {
        AFM_AUDIO_PARAM_RENDERER param_renderer;
        IL_TOOL_INIT_CONFIG_STRUCT(param_renderer);
        param_renderer.nBoardRC = adm_is_rc_in_board();
        il_tool_SetConfig(  Handle,
                            AFM_IndexParamRenderer , &param_renderer);
    }
#endif
    ALOG_INFO("Leave adm_adaptions_setup_comp\n");
    return res;
}
static int GetMICChannelCount(sqlite3* db_p, const char* dev)
{
    int rc = SQLITE_OK;
    sqlite3_stmt *stmt = NULL;
    const char* dev_top = NULL;
    char* command = malloc(1024 * sizeof(char));
    int nChannels = -1;
    ste_adm_res_t res;

    res = adm_db_toplevel_mapping_get(dev, &dev_top);
    if (res != STE_ADM_RES_OK) {
        ALOG_ERR("%s: ERROR: Unable to get top-level device for %s!", __func__, dev);
        goto cleanup;
    }

    memset((void*)command, 0, 1024);
    strcat(command, "SELECT Value FROM StructData "
           "WHERE Name = ( "
           "SELECT Template_Config.StructData FROM Template_Config "
           "WHERE Name = ( "
           "SELECT Device.IOTemplateName FROM Device "
           "WHERE Device.Name = '");
    strcat(command,             dev_top);
    strcat(command,         "' ) "
           ")"
           "AND Param = 'nChannels'");
    ALOG_INFO("Query: %s", command);

    rc = sqlite3_prepare_v2(db_p, command, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        ALOG_ERR("%s: ERROR: Unable to prepare SQL-statement!", __func__);
        goto cleanup;
    }

    if (sqlite3_step(stmt) != SQLITE_ROW)
        goto cleanup;

    nChannels = sqlite3_column_int(stmt, 0);
    if (nChannels <= 0) {
        ALOG_ERR("%s: ERROR: Illegal number of channels (nChannels = %d)!\n", __func__, nChannels);
        goto cleanup;
    }

cleanup:
    if (command != NULL) free(command);
    if (stmt != NULL) {
        sqlite3_finalize(stmt);
        stmt = NULL;
    }

    return nChannels;
}
static int usb_close_output(hw_ext_module_t * hw_module,audio_devices_t   device){
    struct usb_internal_data_s * usb_info = (struct usb_internal_data_s *)hw_module->data;
    audio_policy_anm *apm=hw_module->apm;
    struct str_parms *param;

    if(usb_info==NULL)
        return -1;

    switch(usb_info->state) {
        case IO_OPENED:
        case IO_DISCONNECTED:
            //continue treatment
            break;
        case IO_CONNECTED:
            ALOG_WARN("usb_close_output : USB output is not in disconnected state ; Impossible to close it");
            return -1;
            break;
        case IO_CLOSED:
            ALOG_WARN("usb_close_output : already closed");
            return 0;
            break;
        default:
            ALOG_WARN("usb_close_output : unknown state");
    }

    if (usb_info->output_handle <=0 ) {
        ALOG_WARN("USB output is invalid ; Impossible to connect it");
        return -1;
    }
    ALOG_INFO("USB request closing ");
    param = str_parms_create_str("closing");
    str_parms_add_str(param, "closing", "true");
    apm->mp_client_interface->set_parameters(apm->mService, usb_info->output_handle, str_parms_to_str(param), 0);
    str_parms_destroy(param);

    apm->mp_client_interface->close_output(apm->mService, usb_info->output_handle);
    ALOG_INFO("Usb closed ");
    return(usb_init(hw_module));
}
int adm_is_rc_in_board()
{
    static int rc_is_in_board   = -1;
    if(rc_is_in_board == -1)
    {
        FILE * f_rcfilter = fopen("/sys/devices/platform/modem-hwcfg/rcfilter","r");
        if(f_rcfilter){
            if(fscanf(f_rcfilter, "%d", &rc_is_in_board)<=0){
                ALOG_ERR("Unable to read Filter RC information");
                rc_is_in_board = 0;
            }
            fclose(f_rcfilter);
            ALOG_INFO(" Filter RC is present on board : %d" , rc_is_in_board);
        }
        else
        {
            ALOG_INFO(" No file /sys/devices/platform/modem-hwcfg/rcfilter found set rc to 0 ");
            rc_is_in_board = 0;
        }
    }
    return rc_is_in_board;
}
Пример #12
0
int main(int argc, const char * argv[])
{
    StartupConfigure cfg;
    if (!cfg.loadFromFile(CFG_FILE)) {
        ALOG_ERROR("failed to load configure from file:%s", CFG_FILE);
        return -1;
    }

    if (!Server::instance().run(cfg)){
        ALOG_ERROR("can't run the server");
    }
    ALOG_INFO("Server exited");
    return 0;
}
static int GetDeviceDataIndex(sqlite3* db_p, const char* dev_top)
{
    int rc = SQLITE_OK;
    sqlite3_stmt *stmt = NULL;
    int idx_data = -1;
    char* command = malloc(1024 * sizeof(char));

    memset((void*)command, 0, 1024);
    strcat(command, "SELECT Idx_Data FROM HW_Settings_Device "
           "WHERE Device = '");
    strcat(command,     dev_top);
    strcat(command,  "'");
    ALOG_INFO("Query: %s", command);

    rc = sqlite3_prepare_v2(db_p, command, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        ALOG_ERR("%s: ERROR: Unable to prepare SQL-statement!", __func__);
        goto cleanup;
    }

    if (sqlite3_step(stmt) != SQLITE_ROW)
        goto cleanup;

    ALOG_INFO("%s: Found matching HW-settings for device '%s'.", __func__, dev_top);

    idx_data = sqlite3_column_int(stmt, 0);

cleanup:
    if (command != NULL) free(command);
    if (stmt != NULL) {
        sqlite3_finalize(stmt);
        stmt = NULL;
    }

    return idx_data;
}
void il_tool_enable_trace(il_comp_t handle, OMX_U16 traceEnable, OMX_U32 parentHandle)
{
    ENS_CONFIG_TRACESETTINGTYPE trace_cfg;
    IL_TOOL_INIT_CONFIG_STRUCT(trace_cfg);

    trace_cfg.nParentHandle = parentHandle;
    trace_cfg.nTraceEnable  = traceEnable;

    ste_adm_res_t res = il_tool_log_SetConfig(handle, ENS_IndexConfigTraceSetting, &trace_cfg);
    if (res != STE_ADM_RES_OK) {
        ALOG_ERR("0X%x ENS_IndexConfigTraceSettin FAILED 0x%x\n ", handle, res);
    } else {
        ALOG_INFO("0X%x ENS_IndexConfigTraceSettin OK\n ", handle);
    }
}
static int GetComboDataIndex(sqlite3* db_p, char* command)
{
    int rc = SQLITE_OK;
    sqlite3_stmt *stmt = NULL;
    int idx_data = -1;

    ALOG_INFO("Query: %s", command);

    rc = sqlite3_prepare_v2(db_p, command, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        ALOG_ERR("%s: ERROR: Unable to prepare SQL-statement!", __func__);
        goto cleanup;
    }

    if (sqlite3_step(stmt) != SQLITE_ROW)
        goto cleanup;

    ALOG_INFO("%s: Found matching HW-settings: devices = ('%s', '%s', '%s', '%s', '%s', '%s').",
              __func__,
              sqlite3_column_text(stmt, 1),
              sqlite3_column_text(stmt, 2),
              sqlite3_column_text(stmt, 3),
              sqlite3_column_text(stmt, 4),
              sqlite3_column_text(stmt, 5),
              sqlite3_column_text(stmt, 6));

    idx_data = sqlite3_column_int(stmt, 7);

cleanup:
    if (stmt != NULL) {
        sqlite3_finalize(stmt);
        stmt = NULL;
    }

    return idx_data;
}
static int usb_connect_output(hw_ext_module_t * hw_module,
                                                                    audio_devices_t              device,
                                                                    const char*                  CardAndDevice)
{
    audio_policy_anm *apm=hw_module->apm;
    struct usb_internal_data_s * usb_info = (struct usb_internal_data_s *)hw_module->data;
    char *str = NULL;
    struct str_parms *param;

    if(usb_info==NULL) return -1;

    switch(usb_info->state) {
        case IO_OPENED:
        case IO_DISCONNECTED:
            //continue treatment
            break;
        case IO_CLOSED:
            ALOG_WARN("USB output is in closed state ; Impossible to connect it");
            return -1;
            break;
        case IO_CONNECTED:
            ALOG_WARN("usb_connect_output : already connected");
            return 0;
            break;
        default:
            ALOG_WARN("usb_connect_output : unknown state");
    }

    if (usb_info->output_handle <=0 ) {
        ALOG_WARN("USB output is invalid ; Impossible to connect it");
        return -1;
    }

    ALOG_INFO("USB Output = %d, mStrategyRefCount = %d, CardAndDevice =>  %s",
                usb_info->output_handle,usb_info->output_desc.mStrategyRefCount,CardAndDevice);

    // handle USB device connection
    strncpy(usb_info->usb_card_and_device,CardAndDevice, sizeof(char)*MAX_DEVICE_ADDRESS_LEN);
    param = str_parms_create_str(usb_info->usb_card_and_device);
    str = str_parms_to_str(param);
    apm->mp_client_interface->set_parameters(apm->mService, usb_info->output_handle, str, 0);
    str_parms_destroy(param);

    usb_info->state=IO_CONNECTED;
    return 0;
}
static char* GetData(sqlite3* db_p, int idx_data)
{
    int rc = SQLITE_OK;
    sqlite3_stmt *stmt = NULL;
    char* command = malloc(1024 * sizeof(char));
    const unsigned char* data = NULL;
    char* data_ret = NULL;

    memset((void*)command, 0, 1024);
    sprintf(command, "SELECT Data FROM HW_Settings_Data WHERE Idx = %u", idx_data);
    ALOG_INFO("Query: %s", command);

    rc = sqlite3_prepare_v2(db_p, command, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        ALOG_ERR("%s: ERROR: Unable to prepare SQL-statement!", __func__);
        goto cleanup;
    }

    if (sqlite3_step(stmt) != SQLITE_ROW)
        goto cleanup;

    data = sqlite3_column_text(stmt, 0);
    if (data == NULL) {
        ALOG_ERR("%s: ERROR: Data not found (idx_data = %d)!\n", __func__, idx_data);
        goto cleanup;
    }

    data_ret = strdup((const char*)data);
    if (!data_ret) {
        ALOG_ERR("%s: ERROR: strdup() failed\n", __func__);
    }

cleanup:
    if (command != NULL) free(command);
    if (stmt != NULL) {
        sqlite3_finalize(stmt);
        stmt = NULL;
    }

    return data_ret;
}
void force_standard_tunneling(il_comp_t      comp_h)
{
    static const OMX_INDEXTYPE port_type_index[4] = {
        OMX_IndexParamAudioInit,   OMX_IndexParamImageInit,
        OMX_IndexParamVideoInit,   OMX_IndexParamOtherInit
    };

    ALOG_INFO("Setting all ports on %X to standard tunneling\n", comp_h);

    int type_idx;
    for (type_idx=0 ; type_idx < 4 ; type_idx++) {
        OMX_PORT_PARAM_TYPE port_param;
        port_param.nSize             = sizeof(OMX_PORT_PARAM_TYPE);
        port_param.nVersion.nVersion = OMX_VERSION;

        ste_adm_res_t res = il_tool_GetParameter(comp_h,
                    port_type_index[type_idx], &port_param);
        if (res != STE_ADM_RES_OK) {
            ALOG_ERR("GetParameter failed while setting standard tunneling\n");
            return;
        }

        OMX_U32 first_port = port_param.nStartPortNumber;
        OMX_U32 last_port  = port_param.nStartPortNumber + port_param.nPorts;

        // Go through all ports ([first_port,last_port]) and disable them
        // unless they are in the ports_to_keep_enabled list.
        OMX_U32 port_idx;
        for (port_idx=first_port ; port_idx < last_port ; port_idx++) {
            AFM_PARAM_FORCE_STANDARD_TUNNELING fst;
            IL_TOOL_INIT_CONFIG_STRUCT(fst);
            fst.nPortIndex = port_idx;
            fst.bIsStandardTunneling = OMX_TRUE;
            res = il_tool_SetParameter(comp_h, AFM_IndexParamForceStandardTunneling, &fst);
            if (res != STE_ADM_RES_OK) {
                ALOG_ERR("SetParameter failed while setting standard tunneling\n");
                return;
            }
        }
    }
}
static int usb_disconnect_output(hw_ext_module_t * hw_module, audio_devices_t device,
                                                    const char *CardAndDevice)
{
    audio_policy_anm *apm=hw_module->apm;
    struct usb_internal_data_s * usb_info = (struct usb_internal_data_s *)hw_module->data;
    if(usb_info==NULL) return -1;

    switch(usb_info->state) {
        case IO_CONNECTED:
            //continue treatment
            break;
        case IO_CLOSED:
        case IO_OPENED:
        case IO_DISCONNECTED:
            ALOG_WARN("usb_disconnect_output : already disconnected");
            return 0;
            break;
        default:
            ALOG_WARN("usb_disconnect_output : unknown state");
    }

    ALOG_INFO("USBHandleOutputDisconnection() disconnecting  output");

    if (usb_info->output_handle == 0) {
        ALOG_WARN("USBHandleOutputDisconnection() disconnecting USB and no USB output!");
        return ENOSYS;
    }

    if (strcmp(usb_info->usb_card_and_device, CardAndDevice) != 0) {
        ALOG_WARN("USBHandleOutputDisconnection() disconnecting unknow USB sink address %s",
                CardAndDevice);
        return ENOSYS;
    }

    memset(usb_info->usb_card_and_device, 0, MAX_DEVICE_ADDRESS_LEN);
    usb_info->state=IO_DISCONNECTED;
    return 0;
}
void dev_omx_print_port_def_parameters(
                                    OMX_PARAM_PORTDEFINITIONTYPE *portDefParam)
{
    if (portDefParam == NULL)
    {
        ALOG_ERR("portDefParam is NULL");
        return;
    }
    ALOG_INFO("\tnPortIndex: (OMX_U32)%u\n",
        (unsigned int)portDefParam->nPortIndex);
    if (portDefParam->eDir == OMX_DirInput) {
        ALOG_INFO("\teDir: (OMX_DIRTYPE)OMX_DirInput\n");
    } else {
        ALOG_INFO("\teDir: (OMX_DIRTYPE)OMX_DirOutput\n");
    }
    ALOG_INFO("\tnBufferCountActual: (OMX_U32)%u\n",
        (unsigned int)portDefParam->nBufferCountActual);
    ALOG_INFO("\tnBufferCountMin: (OMX_U32)%u\n",
        (unsigned int)portDefParam->nBufferCountMin);
    ALOG_INFO("\tnBufferSize: (OMX_U32)%u\n",
        (unsigned int)portDefParam->nBufferSize);
    ALOG_INFO("\tbEnabled: (OMX_BOOL)%u\n",
        (unsigned int)portDefParam->bEnabled);
    ALOG_INFO("\tbPopulated: (OMX_BOOL)%u\n",
        (unsigned int)portDefParam->bPopulated);
    ALOG_INFO("\tbBuffersContiguous: (OMX_BOOL)%u\n",
        (unsigned int)portDefParam->bBuffersContiguous);
    ALOG_INFO("\tnBufferAlignment: (OMX_U32)%u\n",
        (unsigned int)portDefParam->nBufferAlignment);
    ALOG_INFO("\teDomain: (OMX_PORTDOMAINTYPE)%u\n",
        (unsigned int)portDefParam->eDomain);
}
/**
* enabled=1 io_fd=-1    --> enable port, do not attach io
* enabled=1 io_fd!=-1   --> enable port, attach io to specified fd
*
* enabled=0 io_fd=-1    --> disable port, do not dettach io
* enabled=0 io_fd==0    --> disable port, dettach io
*
*/
ste_adm_res_t il_tool_change_port_state(il_comp_t comp_h, OMX_U32 port, int enabled, int alloc_bufs)
{
    SRV_DBG_ASSERT_IS_WORKER_THREAD;
    ADM_ASSERT(comp_h != NULL);
    ADM_ASSERT(alloc_bufs == 1 || alloc_bufs == 0);

    // Check if port is already in desired state; this is OK for this call.
    OMX_PARAM_PORTDEFINITIONTYPE port_def;
    port_def.nSize             = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
    port_def.nVersion.nVersion = OMX_VERSION;
    port_def.nPortIndex        = port;


    ste_adm_res_t res = il_tool_GetParameter(comp_h,
            OMX_IndexParamPortDefinition, &port_def);
    if (res != STE_ADM_RES_OK) {
        ALOG_ERR("OMX_GetParameter failed\n");
        return res;
    }

    if ((enabled && port_def.bEnabled) || (!enabled && !port_def.bEnabled)) {
        ALOG_INFO("il_tool_change_port_state: Port %d already in requested state\n", port);
        return STE_ADM_RES_OK;
    }

    if (enabled) {
        res = il_tool_SendCommand(comp_h, OMX_CommandPortEnable,
                                         port, NULL);
    } else {
        if (alloc_bufs) {
            il_tool_io_move_towards_idle(comp_h, port);
        }

        res = il_tool_SendCommand(comp_h, OMX_CommandPortDisable,
                                         port, NULL);

        if (alloc_bufs) {
            il_tool_io_wait_until_idle(comp_h, port);
        }
    }

    if (res != STE_ADM_RES_OK) {
        ALOG_ERR("OMX_SendCommand failed\n");
        return res;
    }

    if (alloc_bufs) {
        if (enabled) {
            if (il_tool_io_alloc(comp_h, port, -1)) {
                ALOG_ERR("Failed to allocate io\n");
                return STE_ADM_RES_IL_UNKNOWN_ERROR;
            }
        } else {
            if (il_tool_io_dealloc(comp_h, port)) {
                ALOG_ERR("Problems during buffer deallocation\n");
                return STE_ADM_RES_IL_UNKNOWN_ERROR;
            }
        }
    }

    ADM_SEM_WAIT_WITH_PRINT("il_tool_change_port_state comp=%p port=%d target_state=%s alloc_bufs=%d", il_tool_raw_handle(comp_h), port,
            enabled ? "Enabled" : "Disabled", alloc_bufs);


    // The component must not be busy now (since the
    // semaphore has been taken). Check that no error has
    // occured.
    ADM_ASSERT(!il_tool_cmd_in_progress(comp_h));
    if (il_tool_last_error(comp_h, NULL) != OMX_ErrorNone) {
        ALOG_ERR("Component has received error event\n");
        return STE_ADM_RES_IL_UNKNOWN_ERROR; // FUTURE IMPROVEMENT: Propagate error from event
    }

    return STE_ADM_RES_OK;
}
ste_adm_res_t il_tool_enter_state(OMX_STATETYPE target_state, il_comp_t* components, int num_components)
{
    SRV_DBG_ASSERT_IS_WORKER_THREAD;
    ADM_ASSERT(components != NULL);
    ADM_ASSERT(num_components > 0);
    ADM_ASSERT(target_state == OMX_StateLoaded ||
           target_state == OMX_StateIdle   ||
           target_state == OMX_StateExecuting);

    int i;
    for (i=0 ; i < num_components ; i++) {
        ADM_ASSERT(components[i] != NULL);
        ADM_ASSERT(!il_tool_cmd_in_progress(components[i]));

        components[i]->callback_state.cmd_in_progress = 1;

        ste_adm_res_t res = il_tool_SendCommand(components[i],
                                         OMX_CommandStateSet,
                                         target_state, NULL);
        if (res != STE_ADM_RES_OK) {
            return res;
        }
    }

    // Wait for semaphore 'clicks' from all components
    int sem_timed_out = 0;
    for (i=0 ; i<num_components && !sem_timed_out ; i++) {
        if (g_adm_state_transition_timeout == 0) {
            ADM_SEM_WAIT_WITH_PRINT("il_tool_enter_state: state=%d %d/%d\n", target_state, i+1, num_components);
        } else {
            ALOG_INFO("Waiting for semaphore, with timeout %d\n", g_adm_state_transition_timeout);
            int semres = adm_sem_wait(&g_adm_event_sem, g_adm_state_transition_timeout);
            if (semres) {
                sem_timed_out = 1;
                ALOG_ERR("Semaphore timed out. g_adm_reboot_on_error == 0\n");
            }
        }
    }

    // Needed until IL tool used in all code
    for (i=0 ; i<num_components ; i++) {
        components[i]->callback_state.cmd_in_progress = 0;
    }

    if (sem_timed_out) {
        return STE_ADM_RES_IL_UNKNOWN_ERROR;
    }

    // The components must not be busy now (since the
    // semaphore has been taken). Check that no error has
    // occured.
    for (i=0 ; i<num_components ; i++) {
        ADM_ASSERT(!il_tool_cmd_in_progress(components[i]));

        if (il_tool_last_error(components[i], NULL) != OMX_ErrorNone) {
            return STE_ADM_RES_IL_UNKNOWN_ERROR;
        }
    }

    return STE_ADM_RES_OK;
}
int ste_adm_hw_handler_u8500(sqlite3* db_p, hw_handler_dev_next_fp_t dev_next_fp, hw_handler_dev_to_dev_next_fp_t dev_next_d2d_fp, fadeSpeed_t fadeSpeed)
{
    SRV_DBG_ASSERT_IS_NOT_WORKER_THREAD;
    SRV_DBG_ASSERT_IS_SERIALIZED_REQUEST;

    const char* name = NULL;
    char* dev_names = NULL;
    int ret = 0;
    int ret_func = STE_ADM_RES_ALSA_ERROR;
    char *command = NULL;
    char* data = NULL;
    int is_input, nDev_combo, idx_data;
    bool activeFMRx = false;
    bool activeFMTx = false;
    bool activeOutputDev = false;
    bool activeInputDev = false;
    bool activeInputDev_MIC = false;
    const char* dev_top = NULL;
    bool controls_open = false;

    ALOG_INFO("%s: Enter.", __func__);

    // Make sure that the settings that is written from ADM is not overwritten
    // by any sink or source
    audio_hal_alsa_set_ignore_defaults(true);

    // Create SQL-statement
    ClearFlags();
    command = malloc(1024 * sizeof(char));
    memset(command, 0, 1024);

    nDev_combo = 0;
    strcat(command, "SELECT * FROM HW_Settings_Combo WHERE (Codec = '");
    strcat(command, codec_name_ab8500_p);
    strcat(command, "')");
    while (dev_next_fp(&name) == 0) {
        if (strcmp(name, STE_ADM_DEVICE_STRING_FMRX) == 0) {
            activeFMRx = true;
        } else if (strcmp(name, STE_ADM_DEVICE_STRING_FMTX) == 0) {
            activeFMTx = true;
        } else if (is_asoc_device(name)) {
            if (adm_db_io_info(name, &is_input) != STE_ADM_RES_OK) {
                ALOG_INFO("%s: Warning: Device direction not found for device %s!", __func__, name);
            } else {
                if (is_input == 1) {
                    activeInputDev = true;
                    if (strcmp(name, STE_ADM_DEVICE_STRING_MIC) == 0) {
                        activeInputDev_MIC = true;
                    }
                } else {
                    activeOutputDev = true;
                }
            }
            UpdateFlags(name);
            nDev_combo++;
            strcat(command, " AND ('");
            strcat(command, name);
            strcat(command, "' IN (Dev1, Dev2, Dev3, Dev4, Dev5, Dev6)) ");
        }
    }

    // Become worker thread before opening ALSA controls (to avoid having the
    // "normal-thread" lock at the same time as the ALSA lock)
    srv_become_worker_thread();

    if (audio_hal_alsa_open_controls(card_name_p) < 0) {
        ALOG_ERR("%s: ERROR: Unable to open ALSA-card '%s'!\n", __func__, card_name_p);
        goto cleanup_worker;
    }
    controls_open = true;

    if (nDev_combo == 0) {
        strcat(command, " AND (Dev1 ='')");
    }
    strcat(command, " ORDER BY rowid LIMIT 1");

    /* Combo-data */
    idx_data = GetComboDataIndex(db_p, command);
    if (idx_data == -1) {
        ALOG_INFO("%s: WARNING: Data-index not found (idx_data = %d)!", __func__, idx_data);
        ret_func = STE_ADM_RES_OK;
        goto cleanup_worker;
    }

    data = GetData(db_p, idx_data);
    if (data == NULL) {
        ALOG_ERR("%s: ERROR: Failed to get data with index = %d!", __func__, idx_data);
        goto cleanup_worker;
    }

    ALOG_INFO("%s: Write HW-settings from file to ALSA-interface.", __func__);
    ret = audio_hal_alsa_set_controls_cfg((const char*)data);
    if (ret < 0) {
        ALOG_ERR("%s: ERROR: Failed to write HW-settings! ste_adm_hw_handler_alsa_set_controls returned %d.", __func__, ret);
        goto cleanup_worker;
    }

    if (data != NULL) {
        free(data);
        data = NULL;
    }

    /* Device-data */
    while (dev_next_fp(&name) == 0) {
        if (strlen(name) == 0)
            continue;

        ret = adm_db_toplevel_mapping_get(name, &dev_top);
        if (ret < 0) {
            ALOG_INFO("%s: ERROR: Unable to find top-level device for '%s'!\n", __func__, name);
            ret_func = ret;
            goto cleanup_worker;
        }
        ALOG_INFO("%s: '%s' maps to '%s'\n", __func__, name, dev_top);

        idx_data = GetDeviceDataIndex(db_p, dev_top);
        if (idx_data == -1) {
            ALOG_INFO("%s: No top-level device-specific data exists for '%s'!", __func__, dev_top);
            continue;
        }

        if (data != NULL) {
            free(data);
            data = NULL;
        }
        data = GetData(db_p, idx_data);
        if (data == NULL) {
            ALOG_ERR("%s: ERROR: Failed to get data with index = %d!", __func__, idx_data);
            goto cleanup_worker;
        }

        // Set Digital Gain Fade Speed Switch
        audio_hal_alsa_set_control("Digital Gain Fade Speed Switch", 0, fadeSpeed);

        ALOG_INFO("%s: Write HW-settings for device '%s'.", __func__, dev_top);
        ret = audio_hal_alsa_set_controls_cfg((const char*)data);
        if (ret < 0) {
            ALOG_ERR("%s: ERROR: Failed to write HW-settings! ste_adm_hw_handler_alsa_set_controls returned %d.", __func__, ret);
            goto cleanup_worker;
        }
    };

    /* Appending device to device connections */
    AppendD2D(db_p, dev_next_d2d_fp);
    ExecuteFlags();

    /* FM-devices */
    if (activeFMRx || activeFMTx) {
        ALOG_INFO("%s: FM-device active!", __func__);

        if (activeFMRx) {
            configure_fm_t config;

            if (FM_TYPE_DIGITAL == fmrx_type) {
                ALOG_INFO("%s: FMRx digital active! Setting DA-from-slot and AD-to-slot mapping...", __func__);

                config.type = AUDIO_HAL_DIGITAL;

                audio_hal_alsa_set_control("Digital Interface AD 5 Loopback Switch", 0, 1);
                audio_hal_alsa_set_control("Digital Interface AD 6 Loopback Switch", 0, 1);
                audio_hal_alsa_set_control("Digital Interface AD To Slot 6 Map", 0, 4); // REG_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN
                audio_hal_alsa_set_control("Digital Interface AD To Slot 7 Map", 0, 5); // REG_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD
                audio_hal_alsa_set_control("Digital Interface DA 7 From Slot Map", 0, 24); // Slot 24 -> DA_IN7
                audio_hal_alsa_set_control("Digital Interface DA 8 From Slot Map", 0, 25); // Slot 25 -> DA_IN8
            } else {
                ALOG_INFO("%s: FMRx analog active! Setting DA-from-slot and AD-to-slot mapping...", __func__);

                config.type = AUDIO_HAL_ANALOG;

                audio_hal_alsa_set_control("Digital Interface AD 5 Loopback Switch", 0, 0);
                audio_hal_alsa_set_control("Digital Interface AD 6 Loopback Switch", 0, 0);
                audio_hal_alsa_set_control("Digital Interface AD To Slot 6 Map", 0, 0);
                audio_hal_alsa_set_control("Digital Interface AD To Slot 7 Map", 0, 1);
                audio_hal_alsa_set_control("AD 1 Select Capture Route", 0, 0);
                audio_hal_alsa_set_control("AD 2 Select Capture Route", 0, 0);
                audio_hal_alsa_set_control("Mic 2 or LINR Select Capture Route", 0, 1);
                audio_hal_alsa_set_control("LineIn Left", 0, 1);
                audio_hal_alsa_set_control("LineIn Right", 0, 1);
            }
            audio_hal_configure_channel(AUDIO_HAL_CHANNEL_FMRX, &config);

        } else if (activeFMTx) {
            ALOG_INFO("%s: FMTx active! Setting DA-from-slot and AD-to-slot mapping...", __func__);
            audio_hal_alsa_set_control("Digital Interface AD 5 Loopback Switch", 0, 1);
            audio_hal_alsa_set_control("Digital Interface AD 6 Loopback Switch", 0, 1);
            audio_hal_alsa_set_control("Digital Interface AD To Slot 16 Map", 0, 4); // REG_ADSLOTSELX_AD_OUT5_TO_SLOT_EVEN
            audio_hal_alsa_set_control("Digital Interface AD To Slot 17 Map", 0, 5); // REG_ADSLOTSELX_AD_OUT6_TO_SLOT_ODD
            audio_hal_alsa_set_control("Digital Interface DA 7 From Slot Map", 0, 14); // Slot 14 -> DA_IN7
            audio_hal_alsa_set_control("Digital Interface DA 8 From Slot Map", 0, 15); // Slot 15 -> DA_IN8
        }
    }

    /* Input-devices */
    if (activeInputDev) {
        int ADSel_slot0 = 2; // REG_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN
        int ADSel_slot1 = 1; // REG_ADSLOTSELX_AD_OUT2_TO_SLOT_ODD
        ALOG_INFO("%s: Input-device active!", __func__);
        if (activeInputDev_MIC) {
            int nChannels = GetMICChannelCount(db_p, STE_ADM_DEVICE_STRING_MIC);
            if (mic_type == MICROPHONE_TYPE_DIGITAL) {
                ALOG_INFO("%s: Device MIC actice (mic_type = MICROPHONE_TYPE_DIGITAL, nChannels = %d).", __func__, nChannels);
                ADSel_slot0 = 0;
                ADSel_slot1 = 1;
                audio_hal_alsa_set_control("AD 1 Select Capture Route", 0, 1); // DMic 1
                if (nChannels > 1)
                    audio_hal_alsa_set_control("AD 2 Select Capture Route", 0, 1); // DMic 2
            } else {
                ALOG_INFO("%s: Device MIC active (mic_type = MICROPHONE_TYPE_ANALOG, nChannels = %d).", __func__, nChannels);
                audio_hal_alsa_set_control("AD 3 Select Capture Route", 0, 0); // Mic 1
                if (nChannels > 1) {
                    audio_hal_alsa_set_control("AD 2 Select Capture Route", 0, 0); // LineIn (Mic 2)
                    audio_hal_alsa_set_control("Mic 2 or LINR Select Capture Route", 0, 0); // Mic 2
                } else {
                    // Force dual mono
                    ADSel_slot0 = 2; // REG_ADSLOTSELX_AD_OUT3_TO_SLOT_EVEN
                    ADSel_slot1 = 2; // REG_ADSLOTSELX_AD_OUT3_TO_SLOT_ODD
                }
            }
            audio_hal_alsa_set_control("DMic 1", 0, mic_type == MICROPHONE_TYPE_DIGITAL);
            audio_hal_alsa_set_control("DMic 2", 0, (mic_type == MICROPHONE_TYPE_DIGITAL) && (nChannels > 1));
            audio_hal_alsa_set_control("Mic 1", 0, mic_type != MICROPHONE_TYPE_DIGITAL);
            audio_hal_alsa_set_control("Mic 2", 0, (mic_type != MICROPHONE_TYPE_DIGITAL) && (nChannels > 1));
        }
        audio_hal_alsa_set_control("Digital Interface AD To Slot 0 Map", 0, ADSel_slot0);
        audio_hal_alsa_set_control("Digital Interface AD To Slot 1 Map", 0, ADSel_slot1);
    }

    /* Output-devices */
    if (activeOutputDev) {
        ALOG_INFO("%s: Output-device active! Setting DA from Slot mapping...", __func__);
        audio_hal_alsa_set_control("Digital Interface DA 1 From Slot Map", 0, 8); // Slot 8 -> DA_IN1
        audio_hal_alsa_set_control("Digital Interface DA 2 From Slot Map", 0, 9); // Slot 9 -> DA_IN2
        audio_hal_alsa_set_control("Digital Interface DA 3 From Slot Map", 0, 10); // Slot 10 -> DA_IN3
        audio_hal_alsa_set_control("Digital Interface DA 4 From Slot Map", 0, 11); // Slot 11 -> DA_IN4
        audio_hal_alsa_set_control("Digital Interface DA 5 From Slot Map", 0, 12); // Slot 12 -> DA_IN5
        audio_hal_alsa_set_control("Digital Interface DA 6 From Slot Map", 0, 13); // Slot 13 -> DA_IN6
    }

    ret_func = STE_ADM_RES_OK;

cleanup_worker:
    if (controls_open) {
        audio_hal_alsa_close_controls();
    }
    srv_become_normal_thread();

    if (command != NULL) free(command);
    if (dev_names != NULL) free(dev_names);
    if (data != NULL) free(data);

    ALOG_INFO("%s: Exit (%s).", __func__, (ret_func == STE_ADM_RES_OK) ? "OK" : "ERROR");

    return ret_func;
}
int ste_adm_hw_handler_vc_u8500(sqlite3* db_p, const char* indev, const char* outdev, int fs)
{
    bool ret, vc_on;
    int ret_func = STE_ADM_RES_ALSA_ERROR;
    const char* dev_top = NULL;
    char* outdev_top = NULL;
    char* indev_top = NULL;

    ALOG_INFO("%s: Enter.", __func__);

    vc_on = (indev != NULL) && (outdev != NULL);
    if (vc_on)
        ALOG_INFO("%s: VC on (indev = '%s', outdev = '%s').", __func__, indev, outdev);
    else
        ALOG_INFO("%s: VC off.", __func__);

    // Become worker thread before opening ALSA controls (to avoid having the
    // "normal-thread" lock at the same time as the ALSA lock)
    srv_become_worker_thread();

    audio_hal_alsa_open_controls(card_name_p);

    ret = audio_hal_alsa_set_control("Master Clock Select", 0, vc_on ? 0 : 1); // VC -> SYSCLK,  Non-VC -> ULPCLK
    if (ret < 0) {
        ALOG_ERR("%s: ERROR: Unable to set audio master-clock!\n", __func__, card_name_p);
        goto cleanup;
    }

    if (vc_on) {
        ret = adm_db_toplevel_mapping_get(indev, &dev_top);
        if (ret < 0) {
            ALOG_ERR("%s: ERROR: Unable to find top-level device for '%s'!\n", __func__, indev);
            ret_func = ret;
            goto cleanup;
        }
        indev_top = strdup(dev_top);
        if (!indev_top) {
            ALOG_ERR("%s: ERROR: strdup() failed\n", __func__);
            goto cleanup;
        }

        ret = adm_db_toplevel_mapping_get(outdev, &dev_top);
        if (ret < 0) {
            ALOG_ERR("%s: ERROR: Unable to find top-level device for '%s'!\n", __func__, outdev);
            ret_func = ret;
            goto cleanup;
        }
        outdev_top = strdup(dev_top);
        if (!outdev_top) {
            ALOG_ERR("%s: ERROR: strdup() failed\n", __func__);
            goto cleanup;
        }

        ALOG_INFO("%s: '%s','%s' maps to '%s','%s' (fs = %d)\n", __func__, indev, outdev, indev_top, outdev_top, fs);

        ret = set_filters(db_p, indev_top, outdev_top, fs);
        if (ret < 0) {
            ALOG_ERR("%s: Failed to configure filters! (ret = %d)\n", __func__, ret);
            goto cleanup;
        }

    } else {
        ret = audio_hal_alsa_set_control("Sidetone Left", 0, 0);
        if (ret < 0) {
            ALOG_ERR("%s: ERROR: Unable to disable sidetone left path! (ret = %d)\n", __func__, ret);
            goto cleanup;
        }
        ret = audio_hal_alsa_set_control("Sidetone Right", 0, 0);
        if (ret < 0) {
            ALOG_ERR("%s: ERROR: Unable to disable sidetone right path! (ret = %d)\n", __func__, ret);
            goto cleanup;
        }
        ret = audio_hal_alsa_set_control("ANC Playback Switch", 0, 0);
        if (ret < 0) {
            ALOG_ERR("%s: ERROR: Unable to disable ANC! (ret = %d)\n", __func__, ret);
            goto cleanup;
        }
    }

    ret_func = STE_ADM_RES_OK;

cleanup:
    if (outdev_top != NULL) free(outdev_top);
    if (indev_top != NULL) free(indev_top);

    audio_hal_alsa_close_controls();
    srv_become_normal_thread();

    return ret_func;
}
static int set_filters(sqlite3* db_p, const char* indev_p, const char* outdev_p, int fs)
{
    int ret_func = STE_ADM_RES_ALSA_ERROR;
    char *command = NULL;
    char *c_criteria = NULL;
    const char* preset = NULL;
    sqlite3_stmt *stmt = NULL;
    int ret;
    char str_fs[6];

    ALOG_INFO("%s: Enter.", __func__);

    sprintf(str_fs, "%d", fs);
    c_criteria = malloc(192 * sizeof(char));
    memset(c_criteria, 0, 192 * sizeof(char));
    strcat(c_criteria, " AND SpeechConfig.InDev = '");
    strcat(c_criteria, indev_p);
    strcat(c_criteria, "' AND SpeechConfig.OutDev = '");
    strcat(c_criteria, outdev_p);
    strcat(c_criteria, "' AND SpeechConfig.SampleRate = '");
    strcat(c_criteria, str_fs);
    strcat(c_criteria, "'");

    command = malloc(512 * sizeof(char));
    memset(command, 0, 512 * sizeof(char));
    strcat(command, "SELECT HW_Settings_FIR.* FROM SpeechConfig, HW_Settings_FIR WHERE SpeechConfig.SidetonePreset = HW_Settings_FIR.Preset");
    strcat(command, c_criteria);

    ret = sqlite3_prepare_v2(db_p, command, -1, &stmt, NULL);
    if (ret != SQLITE_OK) {
        ALOG_ERR("%s: Unable to prepare SQL-statement! \"%s\" (ret = %d)\n", __func__, command, ret);
        ret = -1;
        goto cleanup;
    }
    ret = sqlite3_step(stmt);
    if (ret != SQLITE_ROW) {
        ALOG_WARN("%s: No sidetone preset found in DB for indev = '%s', outdev = '%s'!", __func__, indev_p, outdev_p);
        ret = 0;
        goto sidetone_done;
    }

    preset = (const char*)sqlite3_column_text(stmt, 0);
    ALOG_INFO("%s: Found sidetone preset = '%s' matching indev = '%s', outdev = '%s'.", __func__, preset, indev_p, outdev_p);

    ALOG_INFO("%s: Configuring sidetone.", __func__);
    ret = set_sidetone(stmt);
    if (ret < 0) {
        ALOG_ERR("%s: Failed to configure sidetone! (ret = %d)\n", __func__, ret);
        goto cleanup;
    } else {
        ALOG_INFO("%s: Sidetone configured.\n", __func__);
    }

sidetone_done:
    if (stmt != NULL) {
        ret = sqlite3_finalize(stmt);
        stmt = NULL;
        if (ret != SQLITE_OK)
            ALOG_WARN("%s: Failed to destroy prepared statement after use! (ret = %d)", __func__, ret);
    }

    memset(command, 0, 512 * sizeof(char));
    strcat(command, "SELECT HW_Settings_ANC.* FROM SpeechConfig, HW_Settings_ANC WHERE SpeechConfig.ANCPreset = HW_Settings_ANC.Preset");
    strcat(command, c_criteria);
    ret = sqlite3_prepare_v2(db_p, command, -1, &stmt, NULL);
    if (ret != SQLITE_OK) {
        ALOG_ERR("%s: Unable to prepare SQL-statement! \"%s\" (ret = %d)\n", __func__, command, ret);
        ret = -1;
        goto cleanup;
    }
    ret = sqlite3_step(stmt);
    if (ret != SQLITE_ROW) {
        ALOG_WARN("%s: No ANC preset found in DB for indev = '%s', outdev = '%s'.", __func__, indev_p, outdev_p);
        ret = 0;
        goto anc_done;
    }
    preset = (const char*)sqlite3_column_text(stmt, 0);
    ALOG_INFO("%s: Found ANC-preset = '%s' matching indev = '%s', outdev = '%s'.", __func__, preset, indev_p, outdev_p);

    ALOG_INFO("%s: Configuring ANC.", __func__);
    ret = set_anc(stmt);
    if (ret < 0) {
        ALOG_ERR("%s: Failed to configure ANC! (ret = %d)\n", __func__, ret);
        goto cleanup;
    } else {
        ALOG_INFO("%s: ANC configured.\n", __func__);
    }

anc_done:
    ret_func = STE_ADM_RES_OK;

cleanup:
    if (stmt != NULL) {
        ret = sqlite3_finalize(stmt);
        stmt = NULL;
        if (ret != SQLITE_OK)
            ALOG_WARN("%s: Failed to destroy prepared statement after use! (ret = %d)", __func__, ret);
    }

    if (c_criteria != NULL)
        free(c_criteria);
    if (command != NULL)
        free(command);

    ALOG_INFO("%s: Exit (%s).", __func__, (ret_func == STE_ADM_RES_OK) ? "OK" : "ERROR");

    return ret_func;
}
static int set_sidetone(sqlite3_stmt *stmt)
{
    const unsigned int NR_OF_SIDETONE_FIR_COEFFS = 128;
    long sid_fir_coefficients[NR_OF_SIDETONE_FIR_COEFFS];
    unsigned int i;
    int value, ret;
    long gain[2];

    value = sqlite3_column_int(stmt, 1);
    gain[0] = value;
    gain[1] = value;
    ALOG_INFO("%s: Configuring sidetone gain = %d,%d\n", __func__, gain[0], gain[1]);
    ret = audio_hal_alsa_set_control_values("Sidetone Digital Gain Playback Volume", gain);
    if (ret < 0) {
        ALOG_ERR("%s: ERROR: Unable to set sidetone gain! (ret = %d)\n", __func__, ret);
        return ret;
    }
    if (gain[0] == 0 && gain[1] == 0) {
        ALOG_INFO("%s: No need to set sidetone coefficients with zero gain.\n", __func__);
        ret = audio_hal_alsa_set_control("Sidetone Left", 0, 0);
        if (ret < 0) {
            ALOG_ERR("%s: ERROR: Unable to disable sidetone left! (ret = %d)\n", __func__, ret);
            return ret;
        }
        ret = audio_hal_alsa_set_control("Sidetone Right", 0, 0);
        if (ret < 0) {
            ALOG_ERR("%s: ERROR: Unable to disable sidetone right! (ret = %d)\n", __func__, ret);
            return ret;
        }
    }

    // 128 unsigned 16bit FIR-coefficients
    ALOG_INFO("%s: Configuring sidetone FIR-coefficients.\n", __func__);
    for (i = 0; i < NR_OF_SIDETONE_FIR_COEFFS; i++)
        sid_fir_coefficients[i] = sqlite3_column_int(stmt, i + 2);
    ret = audio_hal_alsa_set_control_values("Sidetone FIR Coefficients", sid_fir_coefficients);
    if (ret < 0) {
        ALOG_ERR("%s: ERROR: Unable to set Sidetone FIR-coefficients!\n", __func__);
        return ret;
    }

    for (i = 0; i < MAX_TRIES_SID; i++) {
        ret = audio_hal_alsa_set_control("Sidetone FIR Apply Coefficients", 0, 1);
        if ((ret == 0) || ((ret < 0) && (ret != -EBUSY)))
            break;
        ALOG_INFO("%s: Unable to apply sidetone coefficients (try %d)!\n", __func__, i);
        usleep(5 * 1000);
    }
    if (ret < 0) {
        ALOG_ERR("%s: ERROR: Unable to apply sidetone coefficients (MAX_TRIES_SID = %d)! (ret = %d)\n", __func__, MAX_TRIES_SID, ret);
        return ret;
    }

    ret = audio_hal_alsa_set_control("Sidetone Left Source Playback Route", 0, 2); // 'Mic 1'
    ret |= audio_hal_alsa_set_control("Sidetone Right Source Playback Route", 0, 1); // 'Mic 1'
    if (ret < 0) {
        ALOG_ERR("%s: ERROR: Unable to set sidetone source to 'Mic 1'! (ret = %d)\n", __func__, ret);
        return ret;
    }

    ret = audio_hal_alsa_set_control("Sidetone Left", 0, 1);
    if (ret < 0) {
        ALOG_ERR("%s: ERROR: Unable to enable sidetone left path! (ret = %d)\n", __func__, ret);
        return ret;
    }

    ret = audio_hal_alsa_set_control("Sidetone Right", 0, 1);
    if (ret < 0)
        ALOG_ERR("%s: ERROR: Unable to enable sidetone right path! (ret = %d)\n", __func__, ret);

    return ret;
}