Home | History | Annotate | Download | only in voicefx
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <errno.h>
     18 #include <fcntl.h>
     19 
     20 #define LOG_TAG "eS305VoiceProcessing"
     21 //#define LOG_NDEBUG 0
     22 #include <cutils/log.h>
     23 
     24 #include "eS305VoiceProcessing.h"
     25 #include <audio_effects/effect_aec.h>
     26 #include <audio_effects/effect_ns.h>
     27 #include <audio_effects/effect_agc.h>
     28 
     29 extern "C" {
     30 
     31 //------------------------------------------------------------------------------
     32 // local definitions
     33 //------------------------------------------------------------------------------
     34 
     35 // number of sessions this effect bundle can be used for
     36 #define ADNC_PFX_NUM_SESSION 8
     37 
     38 // types of pre processing modules
     39 enum adnc_pfx_id
     40 {
     41     PFX_ID_AEC = 0,  // Acoustic Echo Cancellation
     42     PFX_ID_NS,       // Noise Suppression
     43     PFX_ID_AGC,      // Automatic Gain Control
     44     PFX_ID_CNT
     45 };
     46 
     47 // Session state
     48 enum adnc_pfx_session_state {
     49     PFX_SESSION_STATE_INIT,        // initialized
     50     PFX_SESSION_STATE_CONFIG       // configuration received
     51 };
     52 
     53 // Effect/Preprocessor state
     54 enum adnc_pfx_effect_state {
     55     PFX_EFFECT_STATE_INIT,         // initialized
     56     PFX_EFFECT_STATE_CREATED,      // effect created
     57     PFX_EFFECT_STATE_CONFIG,       // configuration received/disabled
     58     PFX_EFFECT_STATE_ACTIVE        // active/enabled
     59 };
     60 
     61 typedef struct adnc_pfx_session_s adnc_pfx_session_t;
     62 typedef struct adnc_pfx_effect_s  adnc_pfx_effect_t;
     63 typedef struct adnc_pfx_ops_s     adnc_pfx_ops_t;
     64 
     65 // Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table.
     66 // Function pointer can be null if no action required.
     67 struct adnc_pfx_ops_s {
     68     int (* create)(adnc_pfx_effect_t *fx);
     69     int (* init)(adnc_pfx_effect_t *fx);
     70     int (* reset)(adnc_pfx_effect_t *fx);
     71     void (* enable)(adnc_pfx_effect_t *fx);
     72     void (* disable)(adnc_pfx_effect_t *fx);
     73     int (* set_parameter)(adnc_pfx_effect_t *fx, void *param, void *value);
     74     int (* get_parameter)(adnc_pfx_effect_t *fx, void *param, size_t *size, void *value);
     75     int (* set_device)(adnc_pfx_effect_t *fx, uint32_t device);
     76 };
     77 
     78 // Effect context
     79 struct adnc_pfx_effect_s {
     80     const struct effect_interface_s *itfe;
     81     uint32_t procId;                // type of pre processor (enum adnc_pfx_id)
     82     uint32_t state;                 // current state (enum adnc_pfx_effect_state)
     83     adnc_pfx_session_t *session;     // session the effect is on
     84     const adnc_pfx_ops_t *ops;       // effect ops table
     85 };
     86 
     87 // Session context
     88 struct adnc_pfx_session_s {
     89     uint32_t state;                     // current state (enum adnc_pfx_session_state)
     90     audio_source_t audioSource;
     91     // FIXME not used, delete?
     92     //int audioSessionId;             // audio session ID
     93     int ioHandle;                     // handle of input stream this session is on
     94     uint32_t createdMsk;              // bit field containing IDs of created pre processors
     95     uint32_t activeMsk;               // bit field containing IDs of pre processors currently active
     96     struct adnc_pfx_effect_s effects[PFX_ID_CNT]; // effects in this session
     97 
     98     // effect settings
     99     //   none controllable from public API here
    100 };
    101 
    102 //-----------------------------------------
    103 // forward declarations
    104 //-----------------------------------------
    105 int Adnc_SetNoiseSuppressionInt_l(bool);
    106 int Adnc_SetAutomaticGainControlInt_l(bool);
    107 int Adnc_SetEchoCancellationInt_l(bool);
    108 int Adnc_ReevaluateUsageInt_l(audio_io_handle_t);
    109 int Adnc_SleepInt_l();
    110 
    111 //------------------------------------------------------------------------------
    112 // eS305 control
    113 //------------------------------------------------------------------------------
    114 #define ES305_SYSFS_PATH "/sys/class/i2c-dev/i2c-4/device/4-003e/"
    115 #define ES305_VOICE_PROCESSING_PATH ES305_SYSFS_PATH "voice_processing"
    116 #define ES305_PRESET_PATH           ES305_SYSFS_PATH "preset"
    117 #define ES305_TX_NS_LEVEL_PATH      ES305_SYSFS_PATH "tx_ns_level"
    118 #define ES305_TX_AGC_ENABLE_PATH    ES305_SYSFS_PATH "tx_agc_enable"
    119 #define ES305_AEC_ENABLE_PATH       ES305_SYSFS_PATH "aec_enable"
    120 #define ES305_SLEEP_PATH            ES305_SYSFS_PATH "sleep"
    121 
    122 enum eS305_controls {
    123     ES305_CTRL_VOICE_PROCESSING = 0,
    124     ES305_CTRL_PRESET,
    125     ES305_CTRL_TX_NS_LEVEL,
    126     ES305_CTRL_TX_AGC_ENABLE,
    127     ES305_CTRL_AEC_ENABLE,
    128     ES305_CTRL_SLEEP,
    129     ES305_NUM_CTRL
    130 };
    131 
    132 struct eS305_ctrl_s {
    133     int fd[ES305_NUM_CTRL];
    134     int current_preset;
    135     int requested_preset;
    136     int ioHandle;
    137 };
    138 typedef struct eS305_ctrl_s eS305_ctrl_t;
    139 
    140 static eS305_ctrl_t eS305_ctrl = {
    141         { -1/*vp*/, -1/*preset*/, -1/*ns*/, -1/*agc*/, -1/*aec*/, -1/*sleep*/},
    142         ES305_PRESET_OFF  /*current_preset*/,
    143         ES305_PRESET_INIT /*requested_preset, an invalid preset, different from current_preset*/,
    144         ES305_IO_HANDLE_NONE
    145 };
    146 
    147 //------------------------------------------------------------------------------
    148 // Effect descriptors
    149 //------------------------------------------------------------------------------
    150 
    151 // UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html
    152 // as the pre processing effects are not defined by OpenSL ES
    153 
    154 // Acoustic Echo Cancellation
    155 static const effect_descriptor_t aec_descriptor = {
    156         FX_IID_AEC_, // type
    157         { 0xfd90ff00, 0x0b55, 0x11e2, 0x892e, { 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }, // uuid
    158         EFFECT_CONTROL_API_VERSION,
    159         (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
    160         0, //FIXME indicate CPU load
    161         0, //FIXME indicate memory usage
    162         "Acoustic Echo Canceler",
    163         "Audience"
    164 };
    165 
    166 // Noise suppression
    167 static const effect_descriptor_t ns_descriptor = {
    168         FX_IID_NS_, // type
    169         { 0x08fa98b0, 0x0b56, 0x11e2, 0x892e, { 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }, // uuid
    170         EFFECT_CONTROL_API_VERSION,
    171         (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
    172         0, //FIXME indicate CPU load
    173         0, //FIXME indicate memory usage
    174         "Noise Suppression",
    175         "Audience"
    176 };
    177 
    178 // Automatic Gain Control
    179 static const effect_descriptor_t agc_descriptor = {
    180         FX_IID_AGC_, // type
    181         { 0xe9e87eb0, 0x0b55, 0x11e2, 0x892e, { 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }, // uuid
    182         EFFECT_CONTROL_API_VERSION,
    183         (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
    184         0, //FIXME indicate CPU load
    185         0, //FIXME indicate memory usage
    186         "Automatic Gain Control",
    187         "Audience"
    188 };
    189 
    190 static const effect_descriptor_t *adnc_pfx_descriptors[PFX_ID_CNT] = {
    191         &aec_descriptor,
    192         &ns_descriptor,
    193         &agc_descriptor
    194 };
    195 
    196 
    197 //------------------------------------------------------------------------------
    198 // Helper functions
    199 //------------------------------------------------------------------------------
    200 static const effect_uuid_t * const sAdncUuidTable[PFX_ID_CNT] = {
    201         FX_IID_AEC,
    202         FX_IID_NS,
    203         FX_IID_AGC
    204 };
    205 
    206 const effect_uuid_t * Adnc_ProcIdToUuid(int procId)
    207 {
    208     if (procId >= PFX_ID_CNT) {
    209         return EFFECT_UUID_NULL;
    210     }
    211     return sAdncUuidTable[procId];
    212 }
    213 
    214 uint32_t Adnc_UuidToProcId(const effect_uuid_t * uuid)
    215 {
    216     size_t i;
    217     for (i = 0; i < PFX_ID_CNT; i++) {
    218         if (memcmp(uuid, sAdncUuidTable[i], sizeof(*uuid)) == 0) {
    219             break;
    220         }
    221     }
    222     return i;
    223 }
    224 
    225 
    226 //------------------------------------------------------------------------------
    227 // Acoustic Echo Canceler (AEC)
    228 //------------------------------------------------------------------------------
    229 int aec_init (adnc_pfx_effect_t *effect)
    230 {
    231     ALOGV("aec_init [noop]");
    232     return 0;
    233 }
    234 
    235 int aec_create(adnc_pfx_effect_t *effect)
    236 {
    237     ALOGV("aec_create [noop]");
    238     return aec_init (effect);
    239 }
    240 
    241 int aec_reset(adnc_pfx_effect_t *effect)
    242 {
    243     ALOGV("aec_reset [noop]");
    244     return 0;
    245 }
    246 
    247 int aec_get_parameter(adnc_pfx_effect_t     *effect,
    248                     void              *pParam,
    249                     size_t            *pValueSize,
    250                     void              *pValue)
    251 {
    252     int status = 0;
    253     uint32_t param = *(uint32_t *)pParam;
    254 
    255     if (*pValueSize < sizeof(uint32_t)) {
    256         return -EINVAL;
    257     }
    258     /* NOT SUPPORTED
    259     switch (param) {
    260     case AEC_PARAM_ECHO_DELAY:
    261     case AEC_PARAM_PROPERTIES:
    262         break;
    263     default:
    264         ALOGW("aec_get_parameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
    265         status = -EINVAL;
    266         break;
    267     }
    268     return status;
    269     */
    270     return -EINVAL;
    271 }
    272 
    273 int aec_set_parameter (adnc_pfx_effect_t *effect, void *pParam, void *pValue)
    274 {
    275     int status = 0;
    276     uint32_t param = *(uint32_t *)pParam;
    277     uint32_t value = *(uint32_t *)pValue;
    278 
    279     /* NOT SUPPORTED
    280     switch (param) {
    281     case AEC_PARAM_ECHO_DELAY:
    282     case AEC_PARAM_PROPERTIES:
    283         ALOGV("aec_setParameter() echo delay %d us, status %d", value, status);
    284         break;
    285     default:
    286         ALOGW("aec_setParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
    287         status = -EINVAL;
    288         break;
    289     }
    290     */
    291     return status;
    292 }
    293 
    294 void aec_enable(adnc_pfx_effect_t *effect)
    295 {
    296     ALOGV("aec_enable [noop]");
    297 }
    298 
    299 void aec_disable(adnc_pfx_effect_t *effect)
    300 {
    301     ALOGV("aec_disable [noop]");
    302 }
    303 
    304 int aec_set_device(adnc_pfx_effect_t *effect, uint32_t device)
    305 {
    306     ALOGV("aec_set_device(device=%08x) [noop]", device);
    307 
    308     /*
    309     switch(device) {
    310     case AUDIO_DEVICE_OUT_EARPIECE:
    311         break;
    312     case AUDIO_DEVICE_OUT_SPEAKER:
    313         break;
    314     case AUDIO_DEVICE_OUT_WIRED_HEADSET:
    315     case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
    316     default:
    317         break;
    318     }
    319     */
    320 
    321     return 0;
    322 }
    323 
    324 static const adnc_pfx_ops_t aec_ops = {
    325         aec_create,
    326         aec_init,
    327         aec_reset,
    328         aec_enable,
    329         aec_disable,
    330         aec_set_parameter,
    331         aec_get_parameter,
    332         aec_set_device,
    333 };
    334 
    335 
    336 //------------------------------------------------------------------------------
    337 // Noise Suppression (NS)
    338 //------------------------------------------------------------------------------
    339 int ns_init (adnc_pfx_effect_t *effect)
    340 {
    341     ALOGV("ns_init [noop]");
    342 
    343     return 0;
    344 }
    345 
    346 int ns_create(adnc_pfx_effect_t *effect)
    347 {
    348     ALOGV("ns_create %p", effect);
    349 
    350     return ns_init (effect);
    351 }
    352 
    353 int ns_get_parameter(adnc_pfx_effect_t     *effect,
    354                    void              *pParam,
    355                    size_t            *pValueSize,
    356                    void              *pValue)
    357 {
    358     int status = 0;
    359     return status;
    360 }
    361 
    362 int ns_set_parameter(adnc_pfx_effect_t *effect, void *pParam, void *pValue)
    363 {
    364     int status = 0;
    365     return status;
    366 }
    367 
    368 void ns_enable(adnc_pfx_effect_t *effect)
    369 {
    370     ALOGV("ns_enable [noop]");
    371 }
    372 
    373 void ns_disable(adnc_pfx_effect_t *effect)
    374 {
    375     ALOGV("ns_disable [noop]");
    376 }
    377 
    378 static const adnc_pfx_ops_t ns_ops = {
    379         ns_create,
    380         ns_init,
    381         NULL,
    382         ns_enable,
    383         ns_disable,
    384         ns_set_parameter,
    385         ns_get_parameter,
    386         NULL,
    387 };
    388 
    389 
    390 //------------------------------------------------------------------------------
    391 // Automatic Gain Control (AGC)
    392 //------------------------------------------------------------------------------
    393 int agc_init (adnc_pfx_effect_t *effect)
    394 {
    395     ALOGV("agc_init  [noop]");
    396 
    397     return 0;
    398 }
    399 
    400 int agc_create(adnc_pfx_effect_t *effect)
    401 {
    402     ALOGV("agc_create %p", effect);
    403 
    404     return agc_init (effect);
    405 }
    406 
    407 int agc_get_parameter(adnc_pfx_effect_t     *effect,
    408                    void              *pParam,
    409                    size_t            *pValueSize,
    410                    void              *pValue)
    411 {
    412     int status = 0;
    413     return status;
    414 }
    415 
    416 int agc_set_parameter(adnc_pfx_effect_t *effect, void *pParam, void *pValue)
    417 {
    418     int status = 0;
    419     return status;
    420 }
    421 
    422 void agc_enable(adnc_pfx_effect_t *effect)
    423 {
    424     ALOGV("agc_enable [noop]");
    425 }
    426 
    427 void agc_disable(adnc_pfx_effect_t *effect)
    428 {
    429     ALOGV("agc_disable [noop]");
    430 }
    431 
    432 static const adnc_pfx_ops_t agc_ops = {
    433         agc_create,
    434         agc_init,
    435         NULL,
    436         agc_enable,
    437         agc_disable,
    438         agc_set_parameter,
    439         agc_get_parameter,
    440         NULL,
    441 };
    442 
    443 //------------------------------------------------------------------------------
    444 //
    445 //------------------------------------------------------------------------------
    446 static const adnc_pfx_ops_t *sPreProcOps[PFX_ID_CNT] = {
    447         &aec_ops,
    448         &ns_ops,
    449         &agc_ops
    450 };
    451 
    452 //------------------------------------------------------------------------------
    453 // Pre-processing effect functions
    454 //------------------------------------------------------------------------------
    455 extern const struct effect_interface_s sEffectInterface;
    456 
    457 #define BAD_STATE_ABORT(from, to) \
    458         LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to);
    459 
    460 void AdncSession_SetProcEnabled(adnc_pfx_session_t *session, uint32_t procId, bool enabled);
    461 
    462 int AdncPreProFx_SetState(adnc_pfx_effect_t *effect, uint32_t state)
    463 {
    464     int status = 0;
    465     ALOGV("AdncPreProFx_SetState procId %d, new %d old %d", effect->procId, state, effect->state);
    466     switch(state) {
    467     case PFX_EFFECT_STATE_INIT:
    468         switch(effect->state) {
    469         case PFX_EFFECT_STATE_ACTIVE:
    470             effect->ops->disable(effect);
    471             AdncSession_SetProcEnabled(effect->session, effect->procId, false);
    472         case PFX_EFFECT_STATE_CONFIG:
    473         case PFX_EFFECT_STATE_CREATED:
    474         case PFX_EFFECT_STATE_INIT:
    475             break;
    476         default:
    477             BAD_STATE_ABORT(effect->state, state);
    478         }
    479         break;
    480     case PFX_EFFECT_STATE_CREATED:
    481         switch(effect->state) {
    482         case PFX_EFFECT_STATE_INIT:
    483             status = effect->ops->create(effect);
    484             break;
    485         case PFX_EFFECT_STATE_CREATED:
    486         case PFX_EFFECT_STATE_ACTIVE:
    487         case PFX_EFFECT_STATE_CONFIG:
    488             ALOGE("Effect_SetState invalid transition");
    489             status = -ENOSYS;
    490             break;
    491         default:
    492             BAD_STATE_ABORT(effect->state, state);
    493         }
    494         break;
    495     case PFX_EFFECT_STATE_CONFIG:
    496         switch(effect->state) {
    497         case PFX_EFFECT_STATE_INIT:
    498             ALOGE("Effect_SetState invalid transition");
    499             status = -ENOSYS;
    500             break;
    501         case PFX_EFFECT_STATE_ACTIVE:
    502             effect->ops->disable(effect);
    503             AdncSession_SetProcEnabled(effect->session, effect->procId, false);
    504             break;
    505         case PFX_EFFECT_STATE_CREATED:
    506         case PFX_EFFECT_STATE_CONFIG:
    507             break;
    508         default:
    509             BAD_STATE_ABORT(effect->state, state);
    510         }
    511         break;
    512     case PFX_EFFECT_STATE_ACTIVE:
    513         switch(effect->state) {
    514         case PFX_EFFECT_STATE_INIT:
    515         case PFX_EFFECT_STATE_CREATED:
    516             ALOGE("Effect_SetState invalid transition");
    517             status = -ENOSYS;
    518             break;
    519         case PFX_EFFECT_STATE_ACTIVE:
    520             // enabling an already enabled effect is just ignored
    521             break;
    522         case PFX_EFFECT_STATE_CONFIG:
    523             effect->ops->enable(effect);
    524             AdncSession_SetProcEnabled(effect->session, effect->procId, true);
    525             break;
    526         default:
    527             BAD_STATE_ABORT(effect->state, state);
    528         }
    529         break;
    530     default:
    531         BAD_STATE_ABORT(effect->state, state);
    532     }
    533     if (status == 0) {
    534         effect->state = state;
    535     }
    536     return status;
    537 }
    538 
    539 int AdncPreProFx_Init(adnc_pfx_effect_t *effect, uint32_t procId)
    540 {
    541     ALOGV(" AdncPreProFx_Init(procId=%d)", procId);
    542     effect->itfe = &sEffectInterface;
    543     effect->ops = sPreProcOps[procId];
    544     effect->procId = procId;
    545     effect->state = PFX_EFFECT_STATE_INIT;
    546     return 0;
    547 }
    548 
    549 int AdncPreProFx_Create(adnc_pfx_effect_t *effect,
    550                adnc_pfx_session_t *session,
    551                effect_handle_t  *interface)
    552 {
    553     ALOGV(" AdncPreProFx_Create(effect=%p)", effect);
    554     effect->session = session;
    555     *interface = (effect_handle_t)&effect->itfe;
    556     return AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_CREATED);
    557 }
    558 
    559 int AdncPreProFx_Release(adnc_pfx_effect_t *effect)
    560 {
    561     return AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_INIT);
    562 }
    563 
    564 
    565 //------------------------------------------------------------------------------
    566 // Session functions
    567 //------------------------------------------------------------------------------
    568 /*
    569  *  Initialize a session context.
    570  *  Must be called with a lock on sAdncBundleLock.
    571  */
    572 int AdncSession_Init_l(adnc_pfx_session_t *session)
    573 {
    574     ALOGV("AdncSession_Init()");
    575     size_t i;
    576     int status = 0;
    577 
    578     session->state = PFX_SESSION_STATE_INIT;
    579     session->audioSource = AUDIO_SOURCE_DEFAULT;
    580     //session->audioSessionId = ES305_SESSION_ID_NONE;  // FIXME not used delete?
    581     session->ioHandle = ES305_IO_HANDLE_NONE;
    582     session->createdMsk = 0;
    583     session->activeMsk  = 0;
    584     // initialize each effect for this session context
    585     for (i = 0; i < PFX_ID_CNT && status == 0; i++) {
    586         status = AdncPreProFx_Init(&session->effects[i], i);
    587     }
    588     return status;
    589 }
    590 
    591 /*
    592  * Must be called with a lock on sAdncBundleLock.
    593  */
    594 int AdncSession_CreateEffect_l(adnc_pfx_session_t *session,
    595                              int32_t procId,
    596                              effect_handle_t  *interface)
    597 {
    598     int status = -ENOMEM;
    599     ALOGV("AdncSession_CreateEffect handle=%d procId %d, old createdMsk %08x",
    600             session->ioHandle, procId, session->createdMsk);
    601 
    602     status = AdncPreProFx_Create(&session->effects[procId], session, interface);
    603     if (status >= 0) {
    604         ALOGV("  AdncSession_CreateEffect OK");
    605         session->createdMsk |= (1 << procId);
    606     }
    607     return status;
    608 }
    609 
    610 int AdncSession_SetConfig(adnc_pfx_session_t *session, effect_config_t *config)
    611 {
    612     ALOGV("AdncSession_SetConfig [noop]");
    613     return 0;
    614 }
    615 
    616 void AdncSession_GetConfig(adnc_pfx_session_t *session, effect_config_t *config)
    617 {
    618     ALOGV("AdncSession_GetConfig [noop]");
    619 }
    620 
    621 int AdncSession_SetReverseConfig(adnc_pfx_session_t *session, effect_config_t *config)
    622 {
    623     ALOGV("AdncSession_SetReverseConfig [noop]");
    624     return 0;
    625 }
    626 
    627 void AdncSession_GetReverseConfig(adnc_pfx_session_t *session, effect_config_t *config)
    628 {
    629     ALOGV("AdncSession_GetReverseConfig [noop]");
    630 }
    631 
    632 void AdncSession_SetProcEnabled(adnc_pfx_session_t *session, uint32_t procId, bool enabled)
    633 {
    634     ALOGV("AdncSession_SetProcEnabled [noop] proc %d, enabled %d", procId, enabled);
    635     //no need to reevaluate session settings, if recording is currently ongoing, we'll reevaluate
    636     //  through eS305_AddEffect()
    637 }
    638 
    639 int AdncSession_SetSource(adnc_pfx_session_t *session, audio_source_t source)
    640 {
    641     session->audioSource = source;
    642     return 0;
    643 }
    644 
    645 //------------------------------------------------------------------------------
    646 // Bundle functions
    647 //------------------------------------------------------------------------------
    648 #define ADNC_BUNDLE_NO_INIT 1
    649 static int sAdncBundleInitStatus = ADNC_BUNDLE_NO_INIT;
    650 static adnc_pfx_session_t sAdncSessions[ADNC_PFX_NUM_SESSION];
    651 static pthread_mutex_t sAdncBundleLock;
    652 
    653 /* Returns a session context for the given IO handle
    654  * Returns an existing session context if the IO handle matches, initializes a new one otherwise.
    655  * Returns NULL if no more session contexts are available
    656  * Must be called with a lock on sAdncBundleLock
    657  */
    658 adnc_pfx_session_t *AdncBundle_GetSession_l(int32_t procId, int32_t sessionId, int32_t ioId)
    659 {
    660     size_t i;
    661     for (i = 0; i < ADNC_PFX_NUM_SESSION; i++) {
    662         if (sAdncSessions[i].ioHandle == ioId) {
    663             return &sAdncSessions[i];
    664         }
    665     }
    666     for (i = 0; i < ADNC_PFX_NUM_SESSION; i++) {
    667         if (sAdncSessions[i].ioHandle == ES305_IO_HANDLE_NONE) {
    668             //sAdncSessions[i].audioSessionId = sessionId; // FIXME not used delete?
    669             sAdncSessions[i].ioHandle = ioId;
    670             return &sAdncSessions[i];
    671         }
    672     }
    673     ALOGV("AdncBundle_GetSession_l");
    674     return NULL;
    675 }
    676 
    677 /*
    678  * Must be called with a lock on sAdncBundleLock.
    679  */
    680 int AdncBundle_Init_l() {
    681     size_t i;
    682     int status = 0;
    683 
    684     if (sAdncBundleInitStatus <= 0) {
    685         return sAdncBundleInitStatus;
    686     }
    687     // initialize all the session contexts that this bundle supports
    688     for (i = 0; i < ADNC_PFX_NUM_SESSION && status == 0; i++) {
    689         status = AdncSession_Init_l(&sAdncSessions[i]);
    690     }
    691     sAdncBundleInitStatus = status;
    692     return sAdncBundleInitStatus;
    693 }
    694 
    695 /*
    696  * Must be called with a lock on sAdncBundleLock.
    697  */
    698 int AdncBundle_Release_l() {
    699     ALOGV("AdncBundle_Release_l()");
    700 
    701     Adnc_SleepInt_l();
    702 
    703     for (int i = 0 ; i < ES305_NUM_CTRL ; i++) {
    704         if (eS305_ctrl.fd[i] >= 0) {
    705             close(eS305_ctrl.fd[i]);
    706         }
    707         eS305_ctrl.fd[i] = -1;
    708     }
    709     return 0;
    710 }
    711 
    712 const effect_descriptor_t *AdncBundle_GetDescriptor(const effect_uuid_t *uuid)
    713 {
    714     size_t i;
    715     for (i = 0; i < PFX_ID_CNT; i++) {
    716         if (memcmp(&adnc_pfx_descriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
    717             return adnc_pfx_descriptors[i];
    718         }
    719     }
    720     return NULL;
    721 }
    722 
    723 /*
    724  * Debug only: display session contexts
    725  */
    726 void AdncBundle_logv_dumpSessions() {
    727     ALOGV("Sessions:");
    728     for (int i=0 ; i<ADNC_PFX_NUM_SESSION ; i++) {
    729         ALOGV(" session %d handle=%d cre=%2x act=%2x",
    730            i, sAdncSessions[i].ioHandle, sAdncSessions[i].createdMsk, sAdncSessions[i].activeMsk);
    731     }
    732 }
    733 
    734 //------------------------------------------------------------------------------
    735 // Effect Control Interface Implementation
    736 //------------------------------------------------------------------------------
    737 int AdncVoiceProcessingFx_Command(effect_handle_t  self,
    738                             uint32_t            cmdCode,
    739                             uint32_t            cmdSize,
    740                             void                *pCmdData,
    741                             uint32_t            *replySize,
    742                             void                *pReplyData)
    743 {
    744     adnc_pfx_effect_t * effect = (adnc_pfx_effect_t *) self;
    745     int retsize;
    746     int status;
    747 
    748     if (effect == NULL){
    749         return -EINVAL;
    750     }
    751 
    752     ALOGV("AdncVoiceProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
    753 
    754     switch (cmdCode){
    755         case EFFECT_CMD_INIT:
    756             if (pReplyData == NULL || *replySize != sizeof(int)){
    757                 return -EINVAL;
    758             }
    759             if (effect->ops->init) {
    760                 effect->ops->init(effect);
    761             }
    762             *(int *)pReplyData = 0;
    763             break;
    764 
    765         case EFFECT_CMD_SET_CONFIG: {
    766             if (pCmdData    == NULL||
    767                 cmdSize     != sizeof(effect_config_t)||
    768                 pReplyData  == NULL||
    769                 *replySize  != sizeof(int)){
    770                 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: "
    771                         "EFFECT_CMD_SET_CONFIG: ERROR");
    772                 return -EINVAL;
    773             }
    774 
    775             *(int *)pReplyData = AdncSession_SetConfig(effect->session, (effect_config_t *)pCmdData);
    776 
    777             if (*(int *)pReplyData != 0) {
    778                 break;
    779             }
    780             if (effect->state != PFX_EFFECT_STATE_ACTIVE) {
    781                 *(int *)pReplyData = AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_CONFIG);
    782             }
    783             } break;
    784 
    785         case EFFECT_CMD_GET_CONFIG:
    786             if (pReplyData == NULL ||
    787                 *replySize != sizeof(effect_config_t)) {
    788                 ALOGV("\tLVM_ERROR : AdncVoiceProcessingFx_Command cmdCode Case: "
    789                         "EFFECT_CMD_GET_CONFIG: ERROR");
    790                 return -EINVAL;
    791             }
    792 
    793             AdncSession_GetConfig(effect->session, (effect_config_t *)pReplyData);
    794             break;
    795 
    796         case EFFECT_CMD_SET_CONFIG_REVERSE:
    797             if (pCmdData == NULL ||
    798                 cmdSize != sizeof(effect_config_t) ||
    799                 pReplyData == NULL ||
    800                 *replySize != sizeof(int)) {
    801                 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: "
    802                         "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
    803                 return -EINVAL;
    804             }
    805             *(int *)pReplyData = AdncSession_SetReverseConfig(effect->session,
    806                                                           (effect_config_t *)pCmdData);
    807             if (*(int *)pReplyData != 0) {
    808                 break;
    809             }
    810             break;
    811 
    812         case EFFECT_CMD_GET_CONFIG_REVERSE:
    813             if (pReplyData == NULL ||
    814                 *replySize != sizeof(effect_config_t)){
    815                 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: "
    816                         "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
    817                 return -EINVAL;
    818             }
    819             AdncSession_GetReverseConfig(effect->session, (effect_config_t *)pCmdData);
    820             break;
    821 
    822         case EFFECT_CMD_RESET:
    823             if (effect->ops->reset) {
    824                 effect->ops->reset(effect);
    825             }
    826             break;
    827 
    828         case EFFECT_CMD_GET_PARAM:{
    829             if (pCmdData == NULL ||
    830                     cmdSize < (int)sizeof(effect_param_t) ||
    831                     pReplyData == NULL ||
    832                     *replySize < (int)sizeof(effect_param_t)){
    833                 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: "
    834                         "EFFECT_CMD_GET_PARAM: ERROR");
    835                 return -EINVAL;
    836             }
    837             effect_param_t *p = (effect_param_t *)pCmdData;
    838 
    839             memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
    840 
    841             p = (effect_param_t *)pReplyData;
    842 
    843             int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
    844 
    845             if (effect->ops->get_parameter) {
    846                 p->status = effect->ops->get_parameter(effect, p->data,
    847                                                        (size_t  *)&p->vsize,
    848                                                        p->data + voffset);
    849                 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
    850             }
    851         } break;
    852 
    853         case EFFECT_CMD_SET_PARAM:{
    854             if (pCmdData == NULL||
    855                     cmdSize < (int)sizeof(effect_param_t) ||
    856                     pReplyData == NULL ||
    857                     *replySize != sizeof(int32_t)){
    858                 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: "
    859                         "EFFECT_CMD_SET_PARAM: ERROR");
    860                 return -EINVAL;
    861             }
    862             effect_param_t *p = (effect_param_t *) pCmdData;
    863 
    864             if (p->psize != sizeof(int32_t)){
    865                 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: "
    866                         "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
    867                 return -EINVAL;
    868             }
    869             if (effect->ops->set_parameter) {
    870                 *(int *)pReplyData = effect->ops->set_parameter(effect,
    871                                                                 (void *)p->data,
    872                                                                 p->data + p->psize);
    873             }
    874         } break;
    875 
    876         case EFFECT_CMD_ENABLE:
    877             if (pReplyData == NULL || *replySize != sizeof(int)){
    878                 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
    879                 return -EINVAL;
    880             }
    881             *(int *)pReplyData = AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_ACTIVE);
    882             break;
    883 
    884         case EFFECT_CMD_DISABLE:
    885             if (pReplyData == NULL || *replySize != sizeof(int)){
    886                 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
    887                 return -EINVAL;
    888             }
    889             *(int *)pReplyData  = AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_CONFIG);
    890             break;
    891 
    892         case EFFECT_CMD_SET_DEVICE:
    893         case EFFECT_CMD_SET_INPUT_DEVICE:
    894             if (pCmdData == NULL ||
    895                 cmdSize != sizeof(uint32_t)) {
    896                 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
    897                 return -EINVAL;
    898             }
    899 
    900             if (effect->ops->set_device) {
    901                 effect->ops->set_device(effect, *(uint32_t *)pCmdData);
    902             }
    903             break;
    904 
    905         case EFFECT_CMD_SET_VOLUME:
    906         case EFFECT_CMD_SET_AUDIO_MODE:
    907         case EFFECT_CMD_SET_FEATURE_CONFIG:
    908             break;
    909 
    910         case EFFECT_CMD_SET_AUDIO_SOURCE:
    911             if (pCmdData == NULL ||
    912                     cmdSize != sizeof(uint32_t)) {
    913                 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_AUDIO_SOURCE: ERROR");
    914                 return -EINVAL;
    915             }
    916             return AdncSession_SetSource(effect->session, (audio_source_t) *(uint32_t *)pCmdData);
    917             break;
    918 
    919         default:
    920             return -EINVAL;
    921     }
    922     return 0;
    923 }
    924 
    925 
    926 int AdncVoiceProcessingFx_GetDescriptor(effect_handle_t   self,
    927                                   effect_descriptor_t *pDescriptor)
    928 {
    929     adnc_pfx_effect_t * effect = (adnc_pfx_effect_t *) self;
    930 
    931     if (effect == NULL || pDescriptor == NULL) {
    932         return -EINVAL;
    933     }
    934 
    935     memcpy(pDescriptor, adnc_pfx_descriptors[effect->procId], sizeof(effect_descriptor_t));
    936 
    937     return 0;
    938 }
    939 
    940 
    941 // effect_handle_t interface implementation for effect
    942 const struct effect_interface_s sEffectInterface = {
    943         NULL, /* Process */
    944         AdncVoiceProcessingFx_Command,
    945         AdncVoiceProcessingFx_GetDescriptor,
    946         NULL
    947 };
    948 //------------------------------------------------------------------------------
    949 // Effect Library Interface Implementation
    950 //------------------------------------------------------------------------------
    951 
    952 int adnc_create(const effect_uuid_t *uuid,
    953             int32_t         sessionId,
    954             int32_t         ioId,
    955             effect_handle_t *pInterface)
    956 {
    957     ALOGV("adnc_create: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
    958 
    959     int status = 0;
    960     const effect_descriptor_t *desc;
    961     adnc_pfx_session_t *session;
    962     uint32_t procId;
    963 
    964     pthread_mutex_lock(&sAdncBundleLock);
    965 
    966     if (AdncBundle_Init_l() != 0) {
    967         status = sAdncBundleInitStatus;
    968         goto exit;
    969     }
    970 
    971     desc =  AdncBundle_GetDescriptor(uuid);
    972     if (desc == NULL) {
    973         ALOGW("  adnc_create: fx not found uuid: %08x", uuid->timeLow);
    974         status = -EINVAL;
    975         goto exit;
    976     }
    977     procId = Adnc_UuidToProcId(&desc->type);
    978 
    979     session = AdncBundle_GetSession_l(procId, sessionId, ioId);
    980     if (session == NULL) {
    981         ALOGW("  adnc_create: no more session available");
    982         status = -EINVAL;
    983         goto exit;
    984     }
    985 
    986     status = AdncSession_CreateEffect_l(session, procId, pInterface);
    987 
    988     if (status < 0 && session->createdMsk == 0) {
    989         session->ioHandle = ES305_IO_HANDLE_NONE;
    990     }
    991 
    992 exit:
    993     pthread_mutex_unlock(&sAdncBundleLock);
    994     return status;
    995 }
    996 
    997 int adnc_release(effect_handle_t interface)
    998 {
    999     int i, status = 0;
   1000     ALOGV("adnc_release %p", interface);
   1001 
   1002     // the effect handle comes from the effect framework, ok to cast
   1003     const adnc_pfx_effect_t * fx = (adnc_pfx_effect_t *) interface;
   1004 
   1005     const uint32_t removalMsk = ~(1 << fx->procId);
   1006 
   1007     pthread_mutex_lock(&sAdncBundleLock);
   1008 
   1009     if (AdncBundle_Init_l() != 0) {
   1010         status = sAdncBundleInitStatus;
   1011         goto exit;
   1012     }
   1013 
   1014     if (fx->session->ioHandle == 0) {
   1015         status = -EINVAL;
   1016         goto exit;
   1017     }
   1018 
   1019     // effect is released, flag it as inactive and not created
   1020     fx->session->createdMsk &= removalMsk;
   1021     fx->session->activeMsk  &= removalMsk;
   1022 
   1023     // configuration has changed, reevaluate
   1024     status = Adnc_ReevaluateUsageInt_l(fx->session->ioHandle);
   1025     // not checking the return status here: if there was an error,
   1026     //    we still need to free the session and wouldn't exit here
   1027 
   1028     // free session if it has no more effects
   1029     if (fx->session->createdMsk == 0) {
   1030         ALOGV(" resetting session on handle %d after effect release", fx->session->ioHandle);
   1031         const int statusInit = AdncSession_Init_l(fx->session);
   1032         if (status == 0) {
   1033             status = statusInit;
   1034         }
   1035     }
   1036 
   1037 exit:
   1038     pthread_mutex_unlock(&sAdncBundleLock);
   1039     return status;
   1040 }
   1041 
   1042 int adnc_get_descriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) {
   1043     if (pDescriptor == NULL || uuid == NULL){
   1044         ALOGV("adnc_get_descriptor() invalid params");
   1045         return -EINVAL;
   1046     }
   1047 
   1048     const effect_descriptor_t *desc = AdncBundle_GetDescriptor(uuid);
   1049     if (desc == NULL) {
   1050         ALOGV("adnc_get_descriptor() not found");
   1051         return -EINVAL;
   1052     }
   1053 
   1054     ALOGV("adnc_get_descriptor() got fx %s", desc->name);
   1055 
   1056     memcpy(pDescriptor, desc, sizeof(effect_descriptor_t));
   1057     return 0;
   1058 }
   1059 
   1060 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
   1061     tag : AUDIO_EFFECT_LIBRARY_TAG,
   1062     version : EFFECT_LIBRARY_API_VERSION,
   1063     name : "Audience Voice Preprocessing Library",
   1064     implementor : "The Android Open Source Project",
   1065     create_effect : adnc_create,
   1066     release_effect : adnc_release,
   1067     get_descriptor : adnc_get_descriptor
   1068 };
   1069 
   1070 //-------------------------------------------------------
   1071 // eS305 control interface
   1072 //-------------------------------------------------------
   1073 int Adnc_SetAutomaticGainControlInt_l(bool agc_on)
   1074 {
   1075     ALOGV("Adnc_SetAutomaticGainControlInt_l(%d)", agc_on);
   1076 
   1077     if (eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE] < 0) {
   1078         ALOGV("  opening eS305 path for agc");
   1079         eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE] = open(ES305_TX_AGC_ENABLE_PATH, O_RDWR);
   1080         if (eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE] < 0) {
   1081             ALOGE("  Cannot open eS305 path for agc: %s", strerror(errno));
   1082             return -ENODEV;
   1083         }
   1084     }
   1085 
   1086     if (agc_on) {
   1087         write(eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE], ES305_AGC_ON, strlen(ES305_AGC_ON));
   1088     } else {
   1089         write(eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE], ES305_AEC_OFF, strlen(ES305_AGC_OFF));
   1090     }
   1091     return 0;
   1092 }
   1093 
   1094 int Adnc_SetEchoCancellationInt_l(bool aec_on)
   1095 {
   1096     ALOGV("Adnc_SetEchoCancellationInt_l(%d)", aec_on);
   1097 
   1098     if (eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE] < 0) {
   1099         ALOGV("  opening eS305 path for aec");
   1100         eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE] = open(ES305_AEC_ENABLE_PATH, O_RDWR);
   1101         if (eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE] < 0) {
   1102             ALOGE("  Cannot open eS305 path for aec: %s", strerror(errno));
   1103             return -ENODEV;
   1104         }
   1105     }
   1106 
   1107     if (aec_on) {
   1108         write(eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE], ES305_AEC_ON, strlen(ES305_AEC_ON));
   1109     } else {
   1110         write(eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE], ES305_AEC_OFF, strlen(ES305_AEC_OFF));
   1111     }
   1112     return 0;
   1113 }
   1114 
   1115 int Adnc_SetNoiseSuppressionInt_l(bool ns_on)
   1116 {
   1117     ALOGV("Adnc_SetNoiseSuppressionInt(%d)", ns_on);
   1118 
   1119     if (eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL] < 0) {
   1120         ALOGV("  opening eS305 path for ns");
   1121         eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL] = open(ES305_TX_NS_LEVEL_PATH, O_RDWR);
   1122         if (eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL] < 0) {
   1123             ALOGE("  Cannot open eS305 path for ns: %s", strerror(errno));
   1124             return -ENODEV;
   1125         }
   1126     }
   1127 
   1128     if (ns_on) {
   1129         if (eS305_ctrl.requested_preset == ES305_PRESET_ASRA_HANDHELD) {
   1130             ALOGV("  setting ns to %s", ES305_NS_VOICE_REC_HANDHELD_ON);
   1131             write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL],
   1132                     ES305_NS_VOICE_REC_HANDHELD_ON, strlen(ES305_NS_VOICE_REC_HANDHELD_ON));
   1133         } else if ((eS305_ctrl.requested_preset == ES305_PRESET_ASRA_DESKTOP)
   1134                 || (eS305_ctrl.requested_preset == ES305_PRESET_ASRA_HEADSET)) {
   1135             ALOGV("  setting ns to %s", ES305_NS_VOICE_REC_SINGLE_MIC_ON);
   1136             write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL],
   1137                     ES305_NS_VOICE_REC_SINGLE_MIC_ON, strlen(ES305_NS_VOICE_REC_SINGLE_MIC_ON));
   1138         } else {
   1139             ALOGV("  setting ns to %s", ES305_NS_DEFAULT_ON);
   1140             write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL],
   1141                     ES305_NS_DEFAULT_ON, strlen(ES305_NS_DEFAULT_ON));
   1142         }
   1143     } else {
   1144         ALOGV("  setting ns to %s", ES305_NS_OFF);
   1145         write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL], ES305_NS_OFF, strlen(ES305_NS_OFF));
   1146     }
   1147     return 0;
   1148 }
   1149 
   1150 int Adnc_SetVoiceProcessingInt_l(bool vp_on)
   1151 {
   1152     if (eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING] < 0) {
   1153         ALOGV("  opening eS305 path for VP");
   1154         eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING] = open(ES305_VOICE_PROCESSING_PATH, O_RDWR);
   1155         if (eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING] < 0) {
   1156             ALOGE("    cannot open eS305 path for VP: %s", strerror(errno));
   1157             return -ENODEV;
   1158         }
   1159     }
   1160     if (vp_on) {
   1161         write(eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING], ES305_ON, strlen(ES305_ON));
   1162     } else {
   1163         write(eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING], ES305_OFF, strlen(ES305_OFF));
   1164     }
   1165     return 0;
   1166 }
   1167 
   1168 /*
   1169  * Put the eS305 to sleep
   1170  * Post condition when no error: eS305_ctrl.current_preset == ES305_PRESET_OFF
   1171  */
   1172 int Adnc_SleepInt_l()
   1173 {
   1174     if (eS305_ctrl.current_preset == ES305_PRESET_OFF) {
   1175         return 0;
   1176     }
   1177 
   1178     ALOGV(" Adnc_SleepInt()_l setting VP off + sleep 1");
   1179 
   1180     Adnc_SetVoiceProcessingInt_l(false /*vp_on*/);
   1181 
   1182     ALOGV("  Adnc_SetSleepInt_l");
   1183     if (eS305_ctrl.fd[ES305_CTRL_SLEEP] < 0) {
   1184         ALOGV("  opening eS305 path for sleep");
   1185         eS305_ctrl.fd[ES305_CTRL_SLEEP] = open(ES305_SLEEP_PATH, O_RDWR);
   1186         if (eS305_ctrl.fd[ES305_CTRL_SLEEP] < 0) {
   1187             ALOGE("    cannot open eS305 path for sleep: %s", strerror(errno));
   1188             return -ENODEV;
   1189         }
   1190     }
   1191 
   1192     write(eS305_ctrl.fd[ES305_CTRL_SLEEP], ES305_ON, strlen(ES305_ON));
   1193 
   1194     eS305_ctrl.current_preset = ES305_PRESET_OFF;
   1195 
   1196     return 0;
   1197 }
   1198 
   1199 /*
   1200  * Apply the eS305_ctrl.requested_preset preset after turning VP on
   1201  * Post condition when no error: eS305_ctrl.current_preset == eS305_ctrl.requested_preset
   1202  */
   1203 int Adnc_ApplyPresetInt_l()
   1204 {
   1205     ALOGV("Adnc_ApplyPresetInt() current_preset=%d, requested_preset=%d",
   1206             eS305_ctrl.current_preset, eS305_ctrl.requested_preset);
   1207 
   1208     if (eS305_ctrl.requested_preset == eS305_ctrl.current_preset) {
   1209         ALOGV("  nothing to do, preset %d is current", eS305_ctrl.requested_preset);
   1210         return 0;
   1211     }
   1212 
   1213     // preset off implies going to sleep
   1214     if (eS305_ctrl.requested_preset == ES305_PRESET_OFF) {
   1215         return Adnc_SleepInt_l();
   1216     }
   1217 
   1218     // voice processing must be on before setting the preset
   1219     if ((eS305_ctrl.current_preset == ES305_PRESET_OFF)
   1220             || (eS305_ctrl.current_preset == ES305_PRESET_INIT)) {
   1221         const int status = Adnc_SetVoiceProcessingInt_l(true /*vp_on*/);
   1222         if (status != 0) {
   1223             return status;
   1224         }
   1225     }
   1226 
   1227     if (eS305_ctrl.fd[ES305_CTRL_PRESET] < 0) {
   1228         ALOGV("  opening eS305 path for PRESET");
   1229         eS305_ctrl.fd[ES305_CTRL_PRESET] = open(ES305_PRESET_PATH, O_RDWR);
   1230     }
   1231     if (eS305_ctrl.fd[ES305_CTRL_PRESET] < 0) {
   1232         ALOGE("  Cannot open eS305 path for PRESET: %s", strerror(errno));
   1233         return -ENODEV;
   1234     }
   1235 
   1236     char str[8];
   1237     sprintf(str, "%d", eS305_ctrl.requested_preset);
   1238     write(eS305_ctrl.fd[ES305_CTRL_PRESET], str, strlen(str));
   1239 
   1240     eS305_ctrl.current_preset = eS305_ctrl.requested_preset;
   1241 
   1242     return 0;
   1243 }
   1244 
   1245 
   1246 /*
   1247  * Apply the settings of given the session context
   1248  */
   1249 int Adnc_ApplySettingsFromSessionContextInt_l(adnc_pfx_session_t * session)
   1250 {
   1251     ALOGV("Adnc_ApplySettingsFromSessionContextInt_l cre=%2x ac=%2x handle=%d",
   1252                   session->createdMsk, session->activeMsk, session->ioHandle);
   1253     int status = 0;
   1254 
   1255     if (session->ioHandle != eS305_ctrl.ioHandle) {
   1256         return status;
   1257     }
   1258 
   1259     // NS: special case of noise suppression, always reset according to effect state
   1260     //     as default desirable value might differ from the preset
   1261     const bool ns_on = ((session->activeMsk & (1 << PFX_ID_NS)) != 0);
   1262     status = Adnc_SetNoiseSuppressionInt_l(ns_on /*ns_on*/);
   1263 
   1264     // AEC
   1265     if (session->createdMsk & (1 << PFX_ID_AEC)) {        /* the effect has been created */
   1266         const bool aec_on = ((session->activeMsk & (1 << PFX_ID_AEC)) != 0);
   1267         int aec_status = Adnc_SetEchoCancellationInt_l(aec_on /*aec_on*/);
   1268         if (status == 0) {
   1269             status = aec_status;
   1270         }
   1271     }
   1272 
   1273     // AGC
   1274     if (session->createdMsk & (1 << PFX_ID_AGC)) {        /* the effect has been created */
   1275         const bool agc_on = ((session->activeMsk & (1 << PFX_ID_AGC)) != 0);
   1276         int agc_status = Adnc_SetAutomaticGainControlInt_l(agc_on /*agc_on*/);
   1277         if (status == 0) {
   1278             status = agc_status;
   1279         }
   1280     }
   1281 
   1282     return status;
   1283 }
   1284 
   1285 /*
   1286  * Return a value between 0 and ADNC_PFX_NUM_SESSION-1 if a session context has the given handle,
   1287  *        -1 if the handle isn't in handled by one of the sessions.
   1288  * Must be called with a lock on sAdncBundleLock
   1289  */
   1290 int Adnc_SessionNumberForHandle_l(audio_io_handle_t handle)
   1291 {
   1292     for (int i = 0 ; i < ADNC_PFX_NUM_SESSION ; i++) {
   1293         if (sAdncSessions[i].ioHandle == handle) {
   1294             return i;
   1295         }
   1296     }
   1297     return -1;
   1298 }
   1299 
   1300 
   1301 /*
   1302  * Apply the settings of the session matching the given IO handle.
   1303  * Must be called with a lock on sAdncBundleLock
   1304  */
   1305 int Adnc_ApplySettingsForHandleInt_l(audio_io_handle_t handle)
   1306 {
   1307     ALOGV(" Adnc_ApplySettingsForHandleInt_l(handle=%d)", handle);
   1308     // indicates whether this effect bundle currently has a session context for this IO handle
   1309     bool hasSession = false;
   1310     int status = 0;
   1311     int i;
   1312 
   1313     if (sAdncBundleInitStatus != 0) {
   1314         // This assumes that the default config of the eS305 after setting a preset
   1315         //    is the correct configuration.
   1316         ALOGV(" no effect settings to apply for IO handle %d, no effect bundle", handle);
   1317         return status;
   1318     }
   1319 
   1320     const int sessionId = Adnc_SessionNumberForHandle_l(handle);
   1321     if (sessionId >= 0) {
   1322         ALOGV("  applying settings from session num %d", sessionId);
   1323         status = Adnc_ApplySettingsFromSessionContextInt_l( &sAdncSessions[sessionId] );
   1324     }
   1325     else {
   1326         ALOGV("  no session found for handle %d", handle);
   1327     }
   1328 
   1329     return status;
   1330 }
   1331 
   1332 /*
   1333  * Reevaluate the usage of the eS305 based on the given IO handle.
   1334  * Must be called with a lock on sAdncBundleLock
   1335  */
   1336 int Adnc_ReevaluateUsageInt_l(audio_io_handle_t handle)
   1337 {
   1338     ALOGV(" Adnc_ReevaluateUsageInt_l(handle=%d) current_preset=%d requested_preset=%d",
   1339             handle, eS305_ctrl.current_preset, eS305_ctrl.requested_preset);
   1340     int status = 0;
   1341     if ((eS305_ctrl.requested_preset == ES305_PRESET_OFF) || (handle == ES305_IO_HANDLE_NONE)) {
   1342         status = Adnc_SleepInt_l();
   1343     } else {
   1344         const int sessionId = Adnc_SessionNumberForHandle_l(handle);
   1345         if (sessionId >= 0) {
   1346             // recording active, use the preset only if there is an effect,
   1347             //                   reset preset to off otherwise
   1348             if (sAdncSessions[sessionId].activeMsk != 0) {
   1349                 status = Adnc_ApplyPresetInt_l();
   1350                 if (status == 0) {
   1351                     //apply the settings of the session associated with the handle (if any)
   1352                     status = Adnc_ApplySettingsForHandleInt_l(handle);
   1353                 }
   1354             } else {
   1355                 status = Adnc_SleepInt_l();
   1356             }
   1357         }
   1358     }
   1359     return status;
   1360 }
   1361 
   1362 
   1363 //-------------------------------------------------------
   1364 // eS305 public control interface from HAL
   1365 //-------------------------------------------------------
   1366 int eS305_UsePreset(int preset)
   1367 {
   1368     ALOGV("eS305_UsePreset(%d) current=%d handle=%d",
   1369             preset, eS305_ctrl.current_preset, eS305_ctrl.ioHandle);
   1370 
   1371     int status = 0;
   1372 
   1373     pthread_mutex_lock(&sAdncBundleLock);
   1374 
   1375     //if (preset != -1) { AdncBundle_logv_dumpSessions(); }
   1376 
   1377     // allow preset transition from any preset to any other during recording,
   1378     //    except from one ASRA preset to another
   1379     if (eS305_ctrl.ioHandle != ES305_IO_HANDLE_NONE) {
   1380         switch(eS305_ctrl.current_preset) {
   1381         case ES305_PRESET_ASRA_HANDHELD:
   1382         case ES305_PRESET_ASRA_DESKTOP:
   1383         case ES305_PRESET_ASRA_HEADSET:
   1384             switch(preset) {
   1385             case ES305_PRESET_ASRA_HANDHELD:
   1386             case ES305_PRESET_ASRA_DESKTOP:
   1387             case ES305_PRESET_ASRA_HEADSET:
   1388                 ALOGV("  not switching from ASRA preset %d to %d during voice recognition",
   1389                         eS305_ctrl.current_preset, preset);
   1390                 status = -EINVAL;
   1391                 goto exit;
   1392             default:
   1393                 // transitioning from ASRA to non-ASRA: valid
   1394                 break;
   1395             }
   1396             break;
   1397         default:
   1398             // transitioning from non-ASRA: valid
   1399             break;
   1400         }
   1401     }
   1402 
   1403     eS305_ctrl.requested_preset = preset;
   1404 
   1405     status = AdncBundle_Init_l();
   1406     if (status != 0) {
   1407         ALOGE(" error applying preset, bundle failed to initialize");
   1408         goto exit;
   1409     }
   1410 
   1411     status = Adnc_ReevaluateUsageInt_l(eS305_ctrl.ioHandle);
   1412 
   1413 exit:
   1414     pthread_mutex_unlock(&sAdncBundleLock);
   1415     return status;
   1416 }
   1417 
   1418 
   1419 int eS305_SetActiveIoHandle(audio_io_handle_t handle)
   1420 {
   1421     ALOGV("eS305_SetActiveIoHandle(%d)", handle);
   1422 
   1423     pthread_mutex_lock(&sAdncBundleLock);
   1424 
   1425     int status = AdncBundle_Init_l();
   1426     if (status != 0) {
   1427         ALOGE(" error setting active handle, bundle failed to initialize");
   1428         pthread_mutex_unlock(&sAdncBundleLock);
   1429         return status;
   1430     }
   1431 
   1432     status = Adnc_ReevaluateUsageInt_l(handle);
   1433 
   1434     if (status == 0) {
   1435         eS305_ctrl.ioHandle = handle;
   1436     } else {
   1437         ALOGE("  failed to update for new handle %d (current preset = %d)",
   1438                 handle, eS305_ctrl.current_preset);
   1439     }
   1440 
   1441     pthread_mutex_unlock(&sAdncBundleLock);
   1442 
   1443     return status;
   1444 }
   1445 
   1446 
   1447 int eS305_AddEffect(effect_descriptor_t * descr, audio_io_handle_t handle)
   1448 {
   1449     ALOGV("eS305_AddEffect(handle=%d)", handle);
   1450 
   1451     pthread_mutex_lock(&sAdncBundleLock);
   1452 
   1453     int status = AdncBundle_Init_l();
   1454     if (status != 0) {
   1455         ALOGE(" error setting adding effect, bundle failed to initialize");
   1456         pthread_mutex_unlock(&sAdncBundleLock);
   1457         return status;
   1458     }
   1459 
   1460     if (descr == NULL){
   1461         ALOGV(" eS305_AddEffect() ERROR effect descriptor is NULL");
   1462         pthread_mutex_unlock(&sAdncBundleLock);
   1463         return -EINVAL;
   1464     }
   1465 
   1466     uint32_t procId = Adnc_UuidToProcId(&descr->type);
   1467 
   1468     adnc_pfx_session_t * session = AdncBundle_GetSession_l(
   1469             procId, ES305_SESSION_ID_NONE, handle/*ioId*/);
   1470 
   1471     if (session != NULL) {
   1472         // mark the effect as active
   1473         session->activeMsk  |= (1 << procId);
   1474 
   1475         // update settings if necessary
   1476         Adnc_ReevaluateUsageInt_l(session->ioHandle);
   1477     }
   1478 
   1479     pthread_mutex_unlock(&sAdncBundleLock);
   1480 
   1481     return status;
   1482 }
   1483 
   1484 
   1485 int eS305_RemoveEffect(effect_descriptor_t * descr, audio_io_handle_t handle)
   1486 {
   1487     ALOGV("eS305_RemoveEffect()");
   1488 
   1489     pthread_mutex_lock(&sAdncBundleLock);
   1490 
   1491     int status = AdncBundle_Init_l();
   1492     if (status != 0) {
   1493         ALOGE(" error setting removing effect, bundle failed to initialize");
   1494         pthread_mutex_unlock(&sAdncBundleLock);
   1495         return status;
   1496     }
   1497 
   1498     if (descr == NULL){
   1499         ALOGV(" eS305_AddEffect() ERROR effect descriptor is NULL");
   1500         pthread_mutex_unlock(&sAdncBundleLock);
   1501         return -EINVAL;
   1502     }
   1503 
   1504     uint32_t procId = Adnc_UuidToProcId(&descr->type);
   1505 
   1506     adnc_pfx_session_t * session = AdncBundle_GetSession_l(
   1507             procId, ES305_SESSION_ID_NONE, handle/*ioId*/);
   1508 
   1509     if (session != NULL) {
   1510         // mark the effect as inactive
   1511         session->activeMsk  &= ~(1 << procId);
   1512 
   1513         // update settings if necessary
   1514         Adnc_ReevaluateUsageInt_l(session->ioHandle);
   1515     }
   1516 
   1517     pthread_mutex_unlock(&sAdncBundleLock);
   1518 
   1519     return status;
   1520 }
   1521 
   1522 
   1523 int eS305_Release() {
   1524     ALOGV("eS305_Release()");
   1525 
   1526     pthread_mutex_lock(&sAdncBundleLock);
   1527 
   1528     AdncBundle_Release_l();
   1529 
   1530     pthread_mutex_unlock(&sAdncBundleLock);
   1531 
   1532     return 0;
   1533 }
   1534 
   1535 } // extern "C"
   1536