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 int adnc_query_number_effects(uint32_t *pNumEffects)
    952 {
    953     if (pNumEffects == NULL) {
    954         return -EINVAL;
    955     }
    956     *pNumEffects = PFX_ID_CNT;
    957     return sAdncBundleInitStatus;
    958 }
    959 
    960 int adnc_query_effect(uint32_t index, effect_descriptor_t *pDescriptor)
    961 {
    962     int status = 0;
    963 
    964     pthread_mutex_lock(&sAdncBundleLock);
    965 
    966     if (AdncBundle_Init_l() != 0) {
    967         status = sAdncBundleInitStatus;
    968         goto exit;
    969     }
    970     if (index >= PFX_ID_CNT) {
    971         status = -EINVAL;
    972         goto exit;
    973     }
    974     memcpy(pDescriptor, adnc_pfx_descriptors[index], sizeof(effect_descriptor_t));
    975 
    976 exit:
    977     pthread_mutex_unlock(&sAdncBundleLock);
    978     return status;
    979 }
    980 
    981 int adnc_create(const effect_uuid_t *uuid,
    982             int32_t         sessionId,
    983             int32_t         ioId,
    984             effect_handle_t *pInterface)
    985 {
    986     ALOGV("adnc_create: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
    987 
    988     int status = 0;
    989     const effect_descriptor_t *desc;
    990     adnc_pfx_session_t *session;
    991     uint32_t procId;
    992 
    993     pthread_mutex_lock(&sAdncBundleLock);
    994 
    995     if (AdncBundle_Init_l() != 0) {
    996         status = sAdncBundleInitStatus;
    997         goto exit;
    998     }
    999 
   1000     desc =  AdncBundle_GetDescriptor(uuid);
   1001     if (desc == NULL) {
   1002         ALOGW("  adnc_create: fx not found uuid: %08x", uuid->timeLow);
   1003         status = -EINVAL;
   1004         goto exit;
   1005     }
   1006     procId = Adnc_UuidToProcId(&desc->type);
   1007 
   1008     session = AdncBundle_GetSession_l(procId, sessionId, ioId);
   1009     if (session == NULL) {
   1010         ALOGW("  adnc_create: no more session available");
   1011         status = -EINVAL;
   1012         goto exit;
   1013     }
   1014 
   1015     status = AdncSession_CreateEffect_l(session, procId, pInterface);
   1016 
   1017     if (status < 0 && session->createdMsk == 0) {
   1018         session->ioHandle = ES305_IO_HANDLE_NONE;
   1019     }
   1020 
   1021 exit:
   1022     pthread_mutex_unlock(&sAdncBundleLock);
   1023     return status;
   1024 }
   1025 
   1026 int adnc_release(effect_handle_t interface)
   1027 {
   1028     int i, status = 0;
   1029     ALOGV("adnc_release %p", interface);
   1030 
   1031     // the effect handle comes from the effect framework, ok to cast
   1032     const adnc_pfx_effect_t * fx = (adnc_pfx_effect_t *) interface;
   1033 
   1034     const uint32_t removalMsk = ~(1 << fx->procId);
   1035 
   1036     pthread_mutex_lock(&sAdncBundleLock);
   1037 
   1038     if (AdncBundle_Init_l() != 0) {
   1039         status = sAdncBundleInitStatus;
   1040         goto exit;
   1041     }
   1042 
   1043     if (fx->session->ioHandle == 0) {
   1044         status = -EINVAL;
   1045         goto exit;
   1046     }
   1047 
   1048     // effect is released, flag it as inactive and not created
   1049     fx->session->createdMsk &= removalMsk;
   1050     fx->session->activeMsk  &= removalMsk;
   1051 
   1052     // configuration has changed, reevaluate
   1053     status = Adnc_ReevaluateUsageInt_l(fx->session->ioHandle);
   1054     // not checking the return status here: if there was an error,
   1055     //    we still need to free the session and wouldn't exit here
   1056 
   1057     // free session if it has no more effects
   1058     if (fx->session->createdMsk == 0) {
   1059         ALOGV(" resetting session on handle %d after effect release", fx->session->ioHandle);
   1060         const int statusInit = AdncSession_Init_l(fx->session);
   1061         if (status == 0) {
   1062             status = statusInit;
   1063         }
   1064     }
   1065 
   1066 exit:
   1067     pthread_mutex_unlock(&sAdncBundleLock);
   1068     return status;
   1069 }
   1070 
   1071 int adnc_get_descriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) {
   1072     if (pDescriptor == NULL || uuid == NULL){
   1073         ALOGV("adnc_get_descriptor() invalid params");
   1074         return -EINVAL;
   1075     }
   1076 
   1077     const effect_descriptor_t *desc = AdncBundle_GetDescriptor(uuid);
   1078     if (desc == NULL) {
   1079         ALOGV("adnc_get_descriptor() not found");
   1080         return -EINVAL;
   1081     }
   1082 
   1083     ALOGV("adnc_get_descriptor() got fx %s", desc->name);
   1084 
   1085     memcpy(pDescriptor, desc, sizeof(effect_descriptor_t));
   1086     return 0;
   1087 }
   1088 
   1089 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
   1090     tag : AUDIO_EFFECT_LIBRARY_TAG,
   1091     version : EFFECT_LIBRARY_API_VERSION,
   1092     name : "Audience Voice Preprocessing Library",
   1093     implementor : "The Android Open Source Project",
   1094     query_num_effects : adnc_query_number_effects,
   1095     query_effect : adnc_query_effect,
   1096     create_effect : adnc_create,
   1097     release_effect : adnc_release,
   1098     get_descriptor : adnc_get_descriptor
   1099 };
   1100 
   1101 //-------------------------------------------------------
   1102 // eS305 control interface
   1103 //-------------------------------------------------------
   1104 int Adnc_SetAutomaticGainControlInt_l(bool agc_on)
   1105 {
   1106     ALOGV("Adnc_SetAutomaticGainControlInt_l(%d)", agc_on);
   1107 
   1108     if (eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE] < 0) {
   1109         ALOGV("  opening eS305 path for agc");
   1110         eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE] = open(ES305_TX_AGC_ENABLE_PATH, O_RDWR);
   1111         if (eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE] < 0) {
   1112             ALOGE("  Cannot open eS305 path for agc: %s", strerror(errno));
   1113             return -ENODEV;
   1114         }
   1115     }
   1116 
   1117     if (agc_on) {
   1118         write(eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE], ES305_AGC_ON, strlen(ES305_AGC_ON));
   1119     } else {
   1120         write(eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE], ES305_AEC_OFF, strlen(ES305_AGC_OFF));
   1121     }
   1122     return 0;
   1123 }
   1124 
   1125 int Adnc_SetEchoCancellationInt_l(bool aec_on)
   1126 {
   1127     ALOGV("Adnc_SetEchoCancellationInt_l(%d)", aec_on);
   1128 
   1129     if (eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE] < 0) {
   1130         ALOGV("  opening eS305 path for aec");
   1131         eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE] = open(ES305_AEC_ENABLE_PATH, O_RDWR);
   1132         if (eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE] < 0) {
   1133             ALOGE("  Cannot open eS305 path for aec: %s", strerror(errno));
   1134             return -ENODEV;
   1135         }
   1136     }
   1137 
   1138     if (aec_on) {
   1139         write(eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE], ES305_AEC_ON, strlen(ES305_AEC_ON));
   1140     } else {
   1141         write(eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE], ES305_AEC_OFF, strlen(ES305_AEC_OFF));
   1142     }
   1143     return 0;
   1144 }
   1145 
   1146 int Adnc_SetNoiseSuppressionInt_l(bool ns_on)
   1147 {
   1148     ALOGV("Adnc_SetNoiseSuppressionInt(%d)", ns_on);
   1149 
   1150     if (eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL] < 0) {
   1151         ALOGV("  opening eS305 path for ns");
   1152         eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL] = open(ES305_TX_NS_LEVEL_PATH, O_RDWR);
   1153         if (eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL] < 0) {
   1154             ALOGE("  Cannot open eS305 path for ns: %s", strerror(errno));
   1155             return -ENODEV;
   1156         }
   1157     }
   1158 
   1159     if (ns_on) {
   1160         if (eS305_ctrl.requested_preset == ES305_PRESET_ASRA_HANDHELD) {
   1161             ALOGV("  setting ns to %s", ES305_NS_VOICE_REC_HANDHELD_ON);
   1162             write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL],
   1163                     ES305_NS_VOICE_REC_HANDHELD_ON, strlen(ES305_NS_VOICE_REC_HANDHELD_ON));
   1164         } else if ((eS305_ctrl.requested_preset == ES305_PRESET_ASRA_DESKTOP)
   1165                 || (eS305_ctrl.requested_preset == ES305_PRESET_ASRA_HEADSET)) {
   1166             ALOGV("  setting ns to %s", ES305_NS_VOICE_REC_SINGLE_MIC_ON);
   1167             write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL],
   1168                     ES305_NS_VOICE_REC_SINGLE_MIC_ON, strlen(ES305_NS_VOICE_REC_SINGLE_MIC_ON));
   1169         } else {
   1170             ALOGV("  setting ns to %s", ES305_NS_DEFAULT_ON);
   1171             write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL],
   1172                     ES305_NS_DEFAULT_ON, strlen(ES305_NS_DEFAULT_ON));
   1173         }
   1174     } else {
   1175         ALOGV("  setting ns to %s", ES305_NS_OFF);
   1176         write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL], ES305_NS_OFF, strlen(ES305_NS_OFF));
   1177     }
   1178     return 0;
   1179 }
   1180 
   1181 int Adnc_SetVoiceProcessingInt_l(bool vp_on)
   1182 {
   1183     if (eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING] < 0) {
   1184         ALOGV("  opening eS305 path for VP");
   1185         eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING] = open(ES305_VOICE_PROCESSING_PATH, O_RDWR);
   1186         if (eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING] < 0) {
   1187             ALOGE("    cannot open eS305 path for VP: %s", strerror(errno));
   1188             return -ENODEV;
   1189         }
   1190     }
   1191     if (vp_on) {
   1192         write(eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING], ES305_ON, strlen(ES305_ON));
   1193     } else {
   1194         write(eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING], ES305_OFF, strlen(ES305_OFF));
   1195     }
   1196     return 0;
   1197 }
   1198 
   1199 /*
   1200  * Put the eS305 to sleep
   1201  * Post condition when no error: eS305_ctrl.current_preset == ES305_PRESET_OFF
   1202  */
   1203 int Adnc_SleepInt_l()
   1204 {
   1205     if (eS305_ctrl.current_preset == ES305_PRESET_OFF) {
   1206         return 0;
   1207     }
   1208 
   1209     ALOGV(" Adnc_SleepInt()_l setting VP off + sleep 1");
   1210 
   1211     Adnc_SetVoiceProcessingInt_l(false /*vp_on*/);
   1212 
   1213     ALOGV("  Adnc_SetSleepInt_l");
   1214     if (eS305_ctrl.fd[ES305_CTRL_SLEEP] < 0) {
   1215         ALOGV("  opening eS305 path for sleep");
   1216         eS305_ctrl.fd[ES305_CTRL_SLEEP] = open(ES305_SLEEP_PATH, O_RDWR);
   1217         if (eS305_ctrl.fd[ES305_CTRL_SLEEP] < 0) {
   1218             ALOGE("    cannot open eS305 path for sleep: %s", strerror(errno));
   1219             return -ENODEV;
   1220         }
   1221     }
   1222 
   1223     write(eS305_ctrl.fd[ES305_CTRL_SLEEP], ES305_ON, strlen(ES305_ON));
   1224 
   1225     eS305_ctrl.current_preset = ES305_PRESET_OFF;
   1226 
   1227     return 0;
   1228 }
   1229 
   1230 /*
   1231  * Apply the eS305_ctrl.requested_preset preset after turning VP on
   1232  * Post condition when no error: eS305_ctrl.current_preset == eS305_ctrl.requested_preset
   1233  */
   1234 int Adnc_ApplyPresetInt_l()
   1235 {
   1236     ALOGV("Adnc_ApplyPresetInt() current_preset=%d, requested_preset=%d",
   1237             eS305_ctrl.current_preset, eS305_ctrl.requested_preset);
   1238 
   1239     if (eS305_ctrl.requested_preset == eS305_ctrl.current_preset) {
   1240         ALOGV("  nothing to do, preset %d is current", eS305_ctrl.requested_preset);
   1241         return 0;
   1242     }
   1243 
   1244     // preset off implies going to sleep
   1245     if (eS305_ctrl.requested_preset == ES305_PRESET_OFF) {
   1246         return Adnc_SleepInt_l();
   1247     }
   1248 
   1249     // voice processing must be on before setting the preset
   1250     if ((eS305_ctrl.current_preset == ES305_PRESET_OFF)
   1251             || (eS305_ctrl.current_preset == ES305_PRESET_INIT)) {
   1252         const int status = Adnc_SetVoiceProcessingInt_l(true /*vp_on*/);
   1253         if (status != 0) {
   1254             return status;
   1255         }
   1256     }
   1257 
   1258     if (eS305_ctrl.fd[ES305_CTRL_PRESET] < 0) {
   1259         ALOGV("  opening eS305 path for PRESET");
   1260         eS305_ctrl.fd[ES305_CTRL_PRESET] = open(ES305_PRESET_PATH, O_RDWR);
   1261     }
   1262     if (eS305_ctrl.fd[ES305_CTRL_PRESET] < 0) {
   1263         ALOGE("  Cannot open eS305 path for PRESET: %s", strerror(errno));
   1264         return -ENODEV;
   1265     }
   1266 
   1267     char str[8];
   1268     sprintf(str, "%d", eS305_ctrl.requested_preset);
   1269     write(eS305_ctrl.fd[ES305_CTRL_PRESET], str, strlen(str));
   1270 
   1271     eS305_ctrl.current_preset = eS305_ctrl.requested_preset;
   1272 
   1273     return 0;
   1274 }
   1275 
   1276 
   1277 /*
   1278  * Apply the settings of given the session context
   1279  */
   1280 int Adnc_ApplySettingsFromSessionContextInt_l(adnc_pfx_session_t * session)
   1281 {
   1282     ALOGV("Adnc_ApplySettingsFromSessionContextInt_l cre=%2x ac=%2x handle=%d",
   1283                   session->createdMsk, session->activeMsk, session->ioHandle);
   1284     int status = 0;
   1285 
   1286     if (session->ioHandle != eS305_ctrl.ioHandle) {
   1287         return status;
   1288     }
   1289 
   1290     // NS: special case of noise suppression, always reset according to effect state
   1291     //     as default desirable value might differ from the preset
   1292     const bool ns_on = ((session->activeMsk & (1 << PFX_ID_NS)) != 0);
   1293     status = Adnc_SetNoiseSuppressionInt_l(ns_on /*ns_on*/);
   1294 
   1295     // AEC
   1296     if ((session->createdMsk & (1 << PFX_ID_AEC))         /* the effect has been created */
   1297             && (session->activeMsk  & (1 << PFX_ID_AEC))) /* the effect is active        */
   1298     {
   1299         Adnc_SetEchoCancellationInt_l(true /*aec_on*/);
   1300     }
   1301 
   1302     // AGC
   1303     if ((session->createdMsk & (1 << PFX_ID_AGC))         /* the effect has been created */
   1304             && (session->activeMsk  & (1 << PFX_ID_AGC))) /* the effect is active        */
   1305     {
   1306         Adnc_SetAutomaticGainControlInt_l(true /*agc_on*/);
   1307     }
   1308 
   1309     return status;
   1310 }
   1311 
   1312 /*
   1313  * Return a value between 0 and ADNC_PFX_NUM_SESSION-1 if a session context has the given handle,
   1314  *        -1 if the handle isn't in handled by one of the sessions.
   1315  * Must be called with a lock on sAdncBundleLock
   1316  */
   1317 int Adnc_SessionNumberForHandle_l(audio_io_handle_t handle)
   1318 {
   1319     for (int i = 0 ; i < ADNC_PFX_NUM_SESSION ; i++) {
   1320         if (sAdncSessions[i].ioHandle == handle) {
   1321             return i;
   1322         }
   1323     }
   1324     return -1;
   1325 }
   1326 
   1327 
   1328 /*
   1329  * Apply the settings of the session matching the given IO handle.
   1330  * Must be called with a lock on sAdncBundleLock
   1331  */
   1332 int Adnc_ApplySettingsForHandleInt_l(audio_io_handle_t handle)
   1333 {
   1334     ALOGV(" Adnc_ApplySettingsForHandleInt_l(handle=%d)", handle);
   1335     // indicates whether this effect bundle currently has a session context for this IO handle
   1336     bool hasSession = false;
   1337     int status = 0;
   1338     int i;
   1339 
   1340     if (sAdncBundleInitStatus != 0) {
   1341         // This assumes that the default config of the eS305 after setting a preset
   1342         //    is the correct configuration.
   1343         ALOGV(" no effect settings to apply for IO handle %d, no effect bundle", handle);
   1344         return status;
   1345     }
   1346 
   1347     const int sessionId = Adnc_SessionNumberForHandle_l(handle);
   1348     if (sessionId >= 0) {
   1349         ALOGV("  applying settings from session num %d", sessionId);
   1350         status = Adnc_ApplySettingsFromSessionContextInt_l( &sAdncSessions[sessionId] );
   1351     }
   1352     else {
   1353         ALOGV("  no session found for handle %d", handle);
   1354     }
   1355 
   1356     return status;
   1357 }
   1358 
   1359 /*
   1360  * Reevaluate the usage of the eS305 based on the given IO handle.
   1361  * Must be called with a lock on sAdncBundleLock
   1362  */
   1363 int Adnc_ReevaluateUsageInt_l(audio_io_handle_t handle)
   1364 {
   1365     ALOGV(" Adnc_ReevaluateUsageInt_l(handle=%d) current_preset=%d requested_preset=%d",
   1366             handle, eS305_ctrl.current_preset, eS305_ctrl.requested_preset);
   1367     int status = 0;
   1368     if ((eS305_ctrl.requested_preset == ES305_PRESET_OFF) || (handle == ES305_IO_HANDLE_NONE)) {
   1369         status = Adnc_SleepInt_l();
   1370     } else {
   1371         const int sessionId = Adnc_SessionNumberForHandle_l(handle);
   1372         if (sessionId >= 0) {
   1373             // recording active, use the preset only if there is an effect,
   1374             //                   reset preset to off otherwise
   1375             if (sAdncSessions[sessionId].activeMsk != 0) {
   1376                 status = Adnc_ApplyPresetInt_l();
   1377                 if (status == 0) {
   1378                     //apply the settings of the session associated with the handle (if any)
   1379                     status = Adnc_ApplySettingsForHandleInt_l(handle);
   1380                 }
   1381             } else {
   1382                 status = Adnc_SleepInt_l();
   1383             }
   1384         }
   1385     }
   1386     return status;
   1387 }
   1388 
   1389 
   1390 //-------------------------------------------------------
   1391 // eS305 public control interface from HAL
   1392 //-------------------------------------------------------
   1393 int eS305_UsePreset(int preset)
   1394 {
   1395     ALOGV("eS305_UsePreset(%d) current=%d handle=%d",
   1396             preset, eS305_ctrl.current_preset, eS305_ctrl.ioHandle);
   1397 
   1398     int status = 0;
   1399 
   1400     pthread_mutex_lock(&sAdncBundleLock);
   1401 
   1402     //if (preset != -1) { AdncBundle_logv_dumpSessions(); }
   1403 
   1404     // allow preset transition from any preset to any other during recording,
   1405     //    except from one ASRA preset to another
   1406     if (eS305_ctrl.ioHandle != ES305_IO_HANDLE_NONE) {
   1407         switch(eS305_ctrl.current_preset) {
   1408         case ES305_PRESET_ASRA_HANDHELD:
   1409         case ES305_PRESET_ASRA_DESKTOP:
   1410         case ES305_PRESET_ASRA_HEADSET:
   1411             switch(preset) {
   1412             case ES305_PRESET_ASRA_HANDHELD:
   1413             case ES305_PRESET_ASRA_DESKTOP:
   1414             case ES305_PRESET_ASRA_HEADSET:
   1415                 ALOGV("  not switching from ASRA preset %d to %d during voice recognition",
   1416                         eS305_ctrl.current_preset, preset);
   1417                 status = -EINVAL;
   1418                 goto exit;
   1419             default:
   1420                 // transitioning from ASRA to non-ASRA: valid
   1421                 break;
   1422             }
   1423             break;
   1424         default:
   1425             // transitioning from non-ASRA: valid
   1426             break;
   1427         }
   1428     }
   1429 
   1430     eS305_ctrl.requested_preset = preset;
   1431 
   1432     status = AdncBundle_Init_l();
   1433     if (status != 0) {
   1434         ALOGE(" error applying preset, bundle failed to initialize");
   1435         goto exit;
   1436     }
   1437 
   1438     status = Adnc_ReevaluateUsageInt_l(eS305_ctrl.ioHandle);
   1439 
   1440 exit:
   1441     pthread_mutex_unlock(&sAdncBundleLock);
   1442     return status;
   1443 }
   1444 
   1445 
   1446 int eS305_SetActiveIoHandle(audio_io_handle_t handle)
   1447 {
   1448     ALOGV("eS305_SetActiveIoHandle(%d)", handle);
   1449 
   1450     pthread_mutex_lock(&sAdncBundleLock);
   1451 
   1452     int status = AdncBundle_Init_l();
   1453     if (status != 0) {
   1454         ALOGE(" error setting active handle, bundle failed to initialize");
   1455         pthread_mutex_unlock(&sAdncBundleLock);
   1456         return status;
   1457     }
   1458 
   1459     status = Adnc_ReevaluateUsageInt_l(handle);
   1460 
   1461     if (status == 0) {
   1462         eS305_ctrl.ioHandle = handle;
   1463     } else {
   1464         ALOGE("  failed to update for new handle %d (current preset = %d)",
   1465                 handle, eS305_ctrl.current_preset);
   1466     }
   1467 
   1468     pthread_mutex_unlock(&sAdncBundleLock);
   1469 
   1470     return status;
   1471 }
   1472 
   1473 
   1474 int eS305_AddEffect(effect_descriptor_t * descr, audio_io_handle_t handle)
   1475 {
   1476     ALOGV("eS305_AddEffect(handle=%d)", handle);
   1477 
   1478     pthread_mutex_lock(&sAdncBundleLock);
   1479 
   1480     int status = AdncBundle_Init_l();
   1481     if (status != 0) {
   1482         ALOGE(" error setting adding effect, bundle failed to initialize");
   1483         pthread_mutex_unlock(&sAdncBundleLock);
   1484         return status;
   1485     }
   1486 
   1487     if (descr == NULL){
   1488         ALOGV(" eS305_AddEffect() ERROR effect descriptor is NULL");
   1489         pthread_mutex_unlock(&sAdncBundleLock);
   1490         return -EINVAL;
   1491     }
   1492 
   1493     uint32_t procId = Adnc_UuidToProcId(&descr->type);
   1494 
   1495     adnc_pfx_session_t * session = AdncBundle_GetSession_l(
   1496             procId, ES305_SESSION_ID_NONE, handle/*ioId*/);
   1497 
   1498     if (session != NULL) {
   1499         // mark the effect as active
   1500         session->activeMsk  |= (1 << procId);
   1501 
   1502         // update settings if necessary
   1503         Adnc_ReevaluateUsageInt_l(session->ioHandle);
   1504     }
   1505 
   1506     pthread_mutex_unlock(&sAdncBundleLock);
   1507 
   1508     return status;
   1509 }
   1510 
   1511 
   1512 int eS305_RemoveEffect(effect_descriptor_t * descr, audio_io_handle_t handle)
   1513 {
   1514     ALOGV("eS305_RemoveEffect()");
   1515 
   1516     pthread_mutex_lock(&sAdncBundleLock);
   1517 
   1518     int status = AdncBundle_Init_l();
   1519     if (status != 0) {
   1520         ALOGE(" error setting removing effect, bundle failed to initialize");
   1521         pthread_mutex_unlock(&sAdncBundleLock);
   1522         return status;
   1523     }
   1524 
   1525     if (descr == NULL){
   1526         ALOGV(" eS305_AddEffect() ERROR effect descriptor is NULL");
   1527         pthread_mutex_unlock(&sAdncBundleLock);
   1528         return -EINVAL;
   1529     }
   1530 
   1531     uint32_t procId = Adnc_UuidToProcId(&descr->type);
   1532 
   1533     adnc_pfx_session_t * session = AdncBundle_GetSession_l(
   1534             procId, ES305_SESSION_ID_NONE, handle/*ioId*/);
   1535 
   1536     if (session != NULL) {
   1537         // mark the effect as inactive
   1538         session->activeMsk  &= ~(1 << procId);
   1539 
   1540         // update settings if necessary
   1541         Adnc_ReevaluateUsageInt_l(session->ioHandle);
   1542     }
   1543 
   1544     pthread_mutex_unlock(&sAdncBundleLock);
   1545 
   1546     return status;
   1547 }
   1548 
   1549 
   1550 int eS305_Release() {
   1551     ALOGV("eS305_Release()");
   1552 
   1553     pthread_mutex_lock(&sAdncBundleLock);
   1554 
   1555     AdncBundle_Release_l();
   1556 
   1557     pthread_mutex_unlock(&sAdncBundleLock);
   1558 
   1559     return 0;
   1560 }
   1561 
   1562 } // extern "C"
   1563