• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Adnc_ProcIdToUuid(int procId)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 
Adnc_UuidToProcId(const effect_uuid_t * uuid)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 //------------------------------------------------------------------------------
aec_init(adnc_pfx_effect_t * effect)229 int aec_init (adnc_pfx_effect_t *effect)
230 {
231     ALOGV("aec_init [noop]");
232     return 0;
233 }
234 
aec_create(adnc_pfx_effect_t * effect)235 int aec_create(adnc_pfx_effect_t *effect)
236 {
237     ALOGV("aec_create [noop]");
238     return aec_init (effect);
239 }
240 
aec_reset(adnc_pfx_effect_t * effect)241 int aec_reset(adnc_pfx_effect_t *effect)
242 {
243     ALOGV("aec_reset [noop]");
244     return 0;
245 }
246 
aec_get_parameter(adnc_pfx_effect_t * effect,void * pParam,size_t * pValueSize,void * pValue)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 
aec_set_parameter(adnc_pfx_effect_t * effect,void * pParam,void * pValue)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 
aec_enable(adnc_pfx_effect_t * effect)294 void aec_enable(adnc_pfx_effect_t *effect)
295 {
296     ALOGV("aec_enable [noop]");
297 }
298 
aec_disable(adnc_pfx_effect_t * effect)299 void aec_disable(adnc_pfx_effect_t *effect)
300 {
301     ALOGV("aec_disable [noop]");
302 }
303 
aec_set_device(adnc_pfx_effect_t * effect,uint32_t device)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 //------------------------------------------------------------------------------
ns_init(adnc_pfx_effect_t * effect)339 int ns_init (adnc_pfx_effect_t *effect)
340 {
341     ALOGV("ns_init [noop]");
342 
343     return 0;
344 }
345 
ns_create(adnc_pfx_effect_t * effect)346 int ns_create(adnc_pfx_effect_t *effect)
347 {
348     ALOGV("ns_create %p", effect);
349 
350     return ns_init (effect);
351 }
352 
ns_get_parameter(adnc_pfx_effect_t * effect,void * pParam,size_t * pValueSize,void * pValue)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 
ns_set_parameter(adnc_pfx_effect_t * effect,void * pParam,void * pValue)362 int ns_set_parameter(adnc_pfx_effect_t *effect, void *pParam, void *pValue)
363 {
364     int status = 0;
365     return status;
366 }
367 
ns_enable(adnc_pfx_effect_t * effect)368 void ns_enable(adnc_pfx_effect_t *effect)
369 {
370     ALOGV("ns_enable [noop]");
371 }
372 
ns_disable(adnc_pfx_effect_t * effect)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 //------------------------------------------------------------------------------
agc_init(adnc_pfx_effect_t * effect)393 int agc_init (adnc_pfx_effect_t *effect)
394 {
395     ALOGV("agc_init  [noop]");
396 
397     return 0;
398 }
399 
agc_create(adnc_pfx_effect_t * effect)400 int agc_create(adnc_pfx_effect_t *effect)
401 {
402     ALOGV("agc_create %p", effect);
403 
404     return agc_init (effect);
405 }
406 
agc_get_parameter(adnc_pfx_effect_t * effect,void * pParam,size_t * pValueSize,void * pValue)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 
agc_set_parameter(adnc_pfx_effect_t * effect,void * pParam,void * pValue)416 int agc_set_parameter(adnc_pfx_effect_t *effect, void *pParam, void *pValue)
417 {
418     int status = 0;
419     return status;
420 }
421 
agc_enable(adnc_pfx_effect_t * effect)422 void agc_enable(adnc_pfx_effect_t *effect)
423 {
424     ALOGV("agc_enable [noop]");
425 }
426 
agc_disable(adnc_pfx_effect_t * effect)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 
AdncPreProFx_SetState(adnc_pfx_effect_t * effect,uint32_t state)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 
AdncPreProFx_Init(adnc_pfx_effect_t * effect,uint32_t procId)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 
AdncPreProFx_Create(adnc_pfx_effect_t * effect,adnc_pfx_session_t * session,effect_handle_t * interface)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 
AdncPreProFx_Release(adnc_pfx_effect_t * effect)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  */
AdncSession_Init_l(adnc_pfx_session_t * session)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  */
AdncSession_CreateEffect_l(adnc_pfx_session_t * session,int32_t procId,effect_handle_t * interface)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 
AdncSession_SetConfig(adnc_pfx_session_t * session,effect_config_t * config)610 int AdncSession_SetConfig(adnc_pfx_session_t *session, effect_config_t *config)
611 {
612     ALOGV("AdncSession_SetConfig [noop]");
613     return 0;
614 }
615 
AdncSession_GetConfig(adnc_pfx_session_t * session,effect_config_t * config)616 void AdncSession_GetConfig(adnc_pfx_session_t *session, effect_config_t *config)
617 {
618     ALOGV("AdncSession_GetConfig [noop]");
619 }
620 
AdncSession_SetReverseConfig(adnc_pfx_session_t * session,effect_config_t * config)621 int AdncSession_SetReverseConfig(adnc_pfx_session_t *session, effect_config_t *config)
622 {
623     ALOGV("AdncSession_SetReverseConfig [noop]");
624     return 0;
625 }
626 
AdncSession_GetReverseConfig(adnc_pfx_session_t * session,effect_config_t * config)627 void AdncSession_GetReverseConfig(adnc_pfx_session_t *session, effect_config_t *config)
628 {
629     ALOGV("AdncSession_GetReverseConfig [noop]");
630 }
631 
AdncSession_SetProcEnabled(adnc_pfx_session_t * session,uint32_t procId,bool enabled)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 
AdncSession_SetSource(adnc_pfx_session_t * session,audio_source_t source)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  */
AdncBundle_GetSession_l(int32_t procId,int32_t sessionId,int32_t ioId)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  */
AdncBundle_Init_l()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  */
AdncBundle_Release_l()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 
AdncBundle_GetDescriptor(const effect_uuid_t * uuid)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  */
AdncBundle_logv_dumpSessions()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 //------------------------------------------------------------------------------
AdncVoiceProcessingFx_Command(effect_handle_t self,uint32_t cmdCode,uint32_t cmdSize,void * pCmdData,uint32_t * replySize,void * pReplyData)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 
AdncVoiceProcessingFx_GetDescriptor(effect_handle_t self,effect_descriptor_t * pDescriptor)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 
adnc_create(const effect_uuid_t * uuid,int32_t sessionId,int32_t ioId,effect_handle_t * pInterface)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 
adnc_release(effect_handle_t interface)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 
adnc_get_descriptor(const effect_uuid_t * uuid,effect_descriptor_t * pDescriptor)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 //-------------------------------------------------------
Adnc_SetAutomaticGainControlInt_l(bool agc_on)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 
Adnc_SetEchoCancellationInt_l(bool aec_on)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 
Adnc_SetNoiseSuppressionInt_l(bool ns_on)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 
Adnc_SetVoiceProcessingInt_l(bool vp_on)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  */
Adnc_SleepInt_l()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  */
Adnc_ApplyPresetInt_l()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  */
Adnc_ApplySettingsFromSessionContextInt_l(adnc_pfx_session_t * session)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  */
Adnc_SessionNumberForHandle_l(audio_io_handle_t handle)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  */
Adnc_ApplySettingsForHandleInt_l(audio_io_handle_t handle)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  */
Adnc_ReevaluateUsageInt_l(audio_io_handle_t handle)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 //-------------------------------------------------------
eS305_UsePreset(int preset)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 
eS305_SetActiveIoHandle(audio_io_handle_t handle)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 
eS305_AddEffect(effect_descriptor_t * descr,audio_io_handle_t handle)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 
eS305_RemoveEffect(effect_descriptor_t * descr,audio_io_handle_t handle)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 
eS305_Release()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