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