10499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent/*
20499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent * Copyright (C) 2014 The Android Open Source Project
30499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent *
40499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
50499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent * you may not use this file except in compliance with the License.
60499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent * You may obtain a copy of the License at
70499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent *
80499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
90499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent *
100499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent * Unless required by applicable law or agreed to in writing, software
110499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
120499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent * See the License for the specific language governing permissions and
140499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent * limitations under the License.
150499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent */
160499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
170499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent#define LOG_TAG "ext_speaker"
180499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent/*#define LOG_NDEBUG 0*/
19e6e2d441c567d5da185b787d6c10ca2c8b36a694Haynes Mathew George#include <log/log.h>
200499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
217c685a1267affc6f96a26f81164b913cd60a3924Vineeta Srivastava#include <stdlib.h>
220499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent#include <audio_hw.h>
230499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent#include <dlfcn.h>
240499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
257ddf867a1a20700aa3242c5d1ab3c621a69ef3e7Andy Hung#ifdef __LP64__
268c83e0ad02470d53917fd1b24ed35e813f345451Diego Wilson#define LIB_SPEAKER_BUNDLE "/vendor/lib64/soundfx/libspeakerbundle.so"
277ddf867a1a20700aa3242c5d1ab3c621a69ef3e7Andy Hung#else
288c83e0ad02470d53917fd1b24ed35e813f345451Diego Wilson#define LIB_SPEAKER_BUNDLE "/vendor/lib/soundfx/libspeakerbundle.so"
297ddf867a1a20700aa3242c5d1ab3c621a69ef3e7Andy Hung#endif
300499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
310499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurenttypedef void (*set_mode_t)(int);
320499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurenttypedef void (*set_speaker_on_t)(bool);
330499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurenttypedef void (*set_earpiece_on_t)(bool);
344cc4ce1a92a47fa1d98c884a33e5e93d3d468b15Eric Laurenttypedef void (*set_voice_vol_t)(float);
350499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
360499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurentstruct speaker_data {
370499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    struct audio_device *adev;
380499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    void *speaker_bundle;
390499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    set_mode_t set_mode;
400499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    set_speaker_on_t set_speaker_on;
410499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    set_earpiece_on_t set_earpiece_on;
420499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    set_voice_vol_t set_voice_vol;
430499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent};
440499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
450499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurentstatic struct speaker_data* open_speaker_bundle()
460499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent{
470499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    struct speaker_data *sd = calloc(1, sizeof(struct speaker_data));
480499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
490499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    sd->speaker_bundle = dlopen(LIB_SPEAKER_BUNDLE, RTLD_NOW);
500499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    if (sd->speaker_bundle == NULL) {
510499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        ALOGE("%s: DLOPEN failed for %s", __func__, LIB_SPEAKER_BUNDLE);
520499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        goto error;
530499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    } else {
540499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        ALOGV("%s: DLOPEN successful for %s", __func__, LIB_SPEAKER_BUNDLE);
550499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
560499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        sd->set_mode = (set_mode_t)dlsym(sd->speaker_bundle,
570499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                                             "set_mode");
580499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        if (sd->set_mode == NULL) {
590499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            ALOGE("%s: dlsym error %s for set_mode", __func__,
600499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                  dlerror());
610499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            goto error;
620499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        }
630499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        sd->set_speaker_on = (set_speaker_on_t)dlsym(sd->speaker_bundle,
640499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                                             "set_speaker_on");
650499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        if (sd->set_speaker_on == NULL) {
660499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            ALOGE("%s: dlsym error %s for set_speaker_on", __func__,
670499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                  dlerror());
680499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            goto error;
690499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        }
700499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        sd->set_earpiece_on = (set_earpiece_on_t)dlsym(sd->speaker_bundle,
710499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                                             "set_earpiece_on");
720499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        if (sd->set_earpiece_on == NULL) {
730499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            ALOGE("%s: dlsym error %s for set_earpiece_on", __func__,
740499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                  dlerror());
750499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            goto error;
760499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        }
770499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        sd->set_voice_vol = (set_voice_vol_t)dlsym(sd->speaker_bundle,
780499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                                             "set_voice_volume");
790499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        if (sd->set_voice_vol == NULL) {
800499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            ALOGE("%s: dlsym error %s for set_voice_volume",
810499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                  __func__, dlerror());
820499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            goto error;
830499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        }
840499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    }
850499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    return sd;
860499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
870499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurenterror:
880499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    free(sd);
890499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    return 0;
900499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent}
910499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
920499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurentstatic void close_speaker_bundle(struct speaker_data *sd)
930499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent{
940499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    if (sd != NULL) {
950499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        dlclose(sd->speaker_bundle);
960499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        free(sd);
970499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        sd = NULL;
980499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    }
990499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent}
1000499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
1010499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurentvoid *audio_extn_extspk_init(struct audio_device *adev)
1020499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent{
1030499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    struct speaker_data *data = open_speaker_bundle();
1040499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
1050499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    if (data)
1060499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        data->adev = adev;
1070499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
1080499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    return data;
1090499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent}
1100499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
1110499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurentvoid audio_extn_extspk_deinit(void *extn)
1120499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent{
1130499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    struct speaker_data *data = (struct speaker_data*)extn;
1140499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    close_speaker_bundle(data);
1150499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent}
1160499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
1170499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurentvoid audio_extn_extspk_update(void* extn)
1180499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent{
1190499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    struct speaker_data *data = (struct speaker_data*)extn;
1200499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
1210499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    if (data) {
1220499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        bool speaker_on = false;
1230499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        bool earpiece_on = false;
1240499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        struct listnode *node;
1250499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        struct audio_usecase *usecase;
1260499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        list_for_each(node, &data->adev->usecase_list) {
1270499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            usecase = node_to_item(node, struct audio_usecase, list);
1280499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            if (usecase->devices & AUDIO_DEVICE_OUT_EARPIECE) {
1290499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
1300499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                    earpiece_on = true;
1310499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                }
1320499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            }
1330499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) {
1340499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
1350499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                    speaker_on = true;
1360499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent                }
1370499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent            }
1380499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        }
1390499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        data->set_earpiece_on(earpiece_on);
1400499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        data->set_speaker_on(speaker_on);
1410499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    }
1420499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent}
1430499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
1440499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurentvoid audio_extn_extspk_set_mode(void* extn, audio_mode_t mode)
1450499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent{
1460499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    struct speaker_data *data = (struct speaker_data*)extn;
1470499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent
1480499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent    if (data)
1490499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent        data->set_mode(mode);
1500499d4fc40cafb9fbb0e8eace1657cfaf79c5699Eric Laurent}
1514cc4ce1a92a47fa1d98c884a33e5e93d3d468b15Eric Laurent
1524cc4ce1a92a47fa1d98c884a33e5e93d3d468b15Eric Laurentvoid audio_extn_extspk_set_voice_vol(void* extn, float vol)
1534cc4ce1a92a47fa1d98c884a33e5e93d3d468b15Eric Laurent{
1544cc4ce1a92a47fa1d98c884a33e5e93d3d468b15Eric Laurent    struct speaker_data *data = (struct speaker_data*)extn;
1554cc4ce1a92a47fa1d98c884a33e5e93d3d468b15Eric Laurent
1564cc4ce1a92a47fa1d98c884a33e5e93d3d468b15Eric Laurent    if (data)
1574cc4ce1a92a47fa1d98c884a33e5e93d3d468b15Eric Laurent        data->set_voice_vol(vol);
1584cc4ce1a92a47fa1d98c884a33e5e93d3d468b15Eric Laurent}
159