blob: 4ef3581efdcf35c6270c55a054551040479ca6ac [file] [log] [blame]
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001/* Copyright (c) 2013-2014, 2016-2020, The Linux Foundation. All rights reserved.
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29#define LOG_TAG "soundtrigger"
30/* #define LOG_NDEBUG 0 */
31#define LOG_NDDEBUG 0
32
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -070033#include <errno.h>
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070034#include <stdbool.h>
35#include <stdlib.h>
36#include <dlfcn.h>
Aalique Grahame22e49102018-12-18 14:23:57 -080037#include <pthread.h>
38#include <log/log.h>
Vinay Vermaaddfa4a2018-04-29 14:03:38 +053039#include <unistd.h>
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070040#include "audio_hw.h"
41#include "audio_extn.h"
42#include "platform.h"
43#include "platform_api.h"
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +053044
45/*-------------------- Begin: AHAL-STHAL Interface ---------------------------*/
46/*
47 * Maintain the proprietary interface between AHAL and STHAL locally to avoid
48 * the compilation dependency of interface header file from STHAL.
49 */
50
51#define MAKE_HAL_VERSION(maj, min) ((((maj) & 0xff) << 8) | ((min) & 0xff))
52#define MAJOR_VERSION(ver) (((ver) & 0xff00) >> 8)
53#define MINOR_VERSION(ver) ((ver) & 0x00ff)
54
55/* Proprietary interface version used for compatibility with STHAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080056#define STHAL_PROP_API_VERSION_2_0 MAKE_HAL_VERSION(2, 0)
57#define STHAL_PROP_API_CURRENT_VERSION STHAL_PROP_API_VERSION_2_0
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +053058
59#define ST_EVENT_CONFIG_MAX_STR_VALUE 32
60#define ST_DEVICE_HANDSET_MIC 1
61
62typedef enum {
63 ST_EVENT_SESSION_REGISTER,
64 ST_EVENT_SESSION_DEREGISTER,
65 ST_EVENT_START_KEEP_ALIVE,
66 ST_EVENT_STOP_KEEP_ALIVE,
kunleiz70e57612018-12-28 17:50:23 +080067 ST_EVENT_UPDATE_ECHO_REF
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +053068} sound_trigger_event_type_t;
69
70typedef enum {
71 AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE,
72 AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE,
73 AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE,
74 AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE,
75 AUDIO_EVENT_STOP_LAB,
76 AUDIO_EVENT_SSR,
77 AUDIO_EVENT_NUM_ST_SESSIONS,
78 AUDIO_EVENT_READ_SAMPLES,
79 AUDIO_EVENT_DEVICE_CONNECT,
80 AUDIO_EVENT_DEVICE_DISCONNECT,
81 AUDIO_EVENT_SVA_EXEC_MODE,
82 AUDIO_EVENT_SVA_EXEC_MODE_STATUS,
83 AUDIO_EVENT_CAPTURE_STREAM_INACTIVE,
84 AUDIO_EVENT_CAPTURE_STREAM_ACTIVE,
Zhou Songc1088ea2018-06-12 00:17:29 +080085 AUDIO_EVENT_BATTERY_STATUS_CHANGED,
kunleiz70e57612018-12-28 17:50:23 +080086 AUDIO_EVENT_GET_PARAM,
Quinn Male918796e2019-07-19 11:19:21 -070087 AUDIO_EVENT_UPDATE_ECHO_REF,
88 AUDIO_EVENT_SCREEN_STATUS_CHANGED
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +053089} audio_event_type_t;
90
91typedef enum {
92 USECASE_TYPE_PCM_PLAYBACK,
93 USECASE_TYPE_PCM_CAPTURE,
94 USECASE_TYPE_VOICE_CALL,
95 USECASE_TYPE_VOIP_CALL,
96} audio_stream_usecase_type_t;
97
98typedef enum {
99 SND_CARD_STATUS_OFFLINE,
100 SND_CARD_STATUS_ONLINE,
101 CPE_STATUS_OFFLINE,
Aalique Grahame22e49102018-12-18 14:23:57 -0800102 CPE_STATUS_ONLINE,
103 SLPI_STATUS_OFFLINE,
104 SLPI_STATUS_ONLINE
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530105} ssr_event_status_t;
106
107struct sound_trigger_session_info {
108 void* p_ses; /* opaque pointer to st_session obj */
109 int capture_handle;
110 struct pcm *pcm;
111 struct pcm_config config;
112};
113
114struct audio_read_samples_info {
115 struct sound_trigger_session_info *ses_info;
116 void *buf;
117 size_t num_bytes;
118};
119
120struct audio_hal_usecase {
121 audio_stream_usecase_type_t type;
122};
123
124struct sound_trigger_event_info {
125 struct sound_trigger_session_info st_ses;
kunleiz70e57612018-12-28 17:50:23 +0800126 bool st_ec_ref_enabled;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530127};
128typedef struct sound_trigger_event_info sound_trigger_event_info_t;
129
130struct sound_trigger_device_info {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800131 struct listnode devices;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530132};
133
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530134struct sound_trigger_get_param_data {
135 char *param;
136 int sm_handle;
137 struct str_parms *reply;
138};
139
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530140struct audio_event_info {
141 union {
142 ssr_event_status_t status;
143 int value;
144 struct sound_trigger_session_info ses_info;
145 struct audio_read_samples_info aud_info;
146 char str_value[ST_EVENT_CONFIG_MAX_STR_VALUE];
147 struct audio_hal_usecase usecase;
kunleiz70e57612018-12-28 17:50:23 +0800148 bool audio_ec_ref_enabled;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530149 struct sound_trigger_get_param_data st_get_param_data;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530150 } u;
151 struct sound_trigger_device_info device_info;
152};
153typedef struct audio_event_info audio_event_info_t;
154/* STHAL callback which is called by AHAL */
155typedef int (*sound_trigger_hw_call_back_t)(audio_event_type_t,
156 struct audio_event_info*);
157
158/*---------------- End: AHAL-STHAL Interface ----------------------------------*/
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700159
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +0530160#ifdef DYNAMIC_LOG_ENABLED
161#include <log_xml_parser.h>
162#define LOG_MASK HAL_MOD_FILE_SND_TRIGGER
163#include <log_utils.h>
164#endif
165
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700166#define XSTR(x) STR(x)
167#define STR(x) #x
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530168#define MAX_LIBRARY_PATH 100
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700169
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530170#define DLSYM(handle, ptr, symbol, err) \
171do {\
Venkatesh Mangalappalibcc684c2018-04-06 14:58:44 -0700172 ptr = dlsym(handle, #symbol); \
173 if (ptr == NULL) {\
174 ALOGW("%s: %s not found. %s", __func__, #symbol, dlerror());\
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530175 err = -ENODEV;\
176 }\
177} while(0)
178
179#ifdef __LP64__
180#define SOUND_TRIGGER_LIBRARY_PATH "/vendor/lib64/hw/sound_trigger.primary.%s.so"
181#else
182#define SOUND_TRIGGER_LIBRARY_PATH "/vendor/lib/hw/sound_trigger.primary.%s.so"
183#endif
184
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530185#define SVA_PARAM_DIRECTION_OF_ARRIVAL "st_direction_of_arrival"
186#define SVA_PARAM_CHANNEL_INDEX "st_channel_index"
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530187#define MAX_STR_LENGTH_FFV_PARAMS 30
188#define MAX_FFV_SESSION_ID 100
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530189/*
190 * Current proprietary API version used by AHAL. Queried by STHAL
191 * for compatibility check with AHAL
192 */
193const unsigned int sthal_prop_api_version = STHAL_PROP_API_CURRENT_VERSION;
194
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700195struct sound_trigger_info {
196 struct sound_trigger_session_info st_ses;
197 bool lab_stopped;
198 struct listnode list;
199};
200
201struct sound_trigger_audio_device {
202 void *lib_handle;
203 struct audio_device *adev;
204 sound_trigger_hw_call_back_t st_callback;
205 struct listnode st_ses_list;
206 pthread_mutex_t lock;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530207 unsigned int sthal_prop_api_version;
kunleiz70e57612018-12-28 17:50:23 +0800208 bool st_ec_ref_enabled;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700209};
210
211static struct sound_trigger_audio_device *st_dev;
212
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530213#if LINUX_ENABLED
214static void get_library_path(char *lib_path)
215{
216 snprintf(lib_path, MAX_LIBRARY_PATH,
Manish Dewangan6a36d002017-10-09 14:11:00 +0530217 "sound_trigger.primary.default.so");
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530218}
219#else
220static void get_library_path(char *lib_path)
221{
222 snprintf(lib_path, MAX_LIBRARY_PATH,
David Ng06ccd872017-03-15 11:39:33 -0700223 "/vendor/lib/hw/sound_trigger.primary.%s.so",
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530224 XSTR(SOUND_TRIGGER_PLATFORM_NAME));
225}
226#endif
227
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700228static struct sound_trigger_info *
229get_sound_trigger_info(int capture_handle)
230{
231 struct sound_trigger_info *st_ses_info = NULL;
232 struct listnode *node;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700233 ALOGV("%s: list empty %d capture_handle %d", __func__,
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700234 list_empty(&st_dev->st_ses_list), capture_handle);
235 list_for_each(node, &st_dev->st_ses_list) {
236 st_ses_info = node_to_item(node, struct sound_trigger_info , list);
237 if (st_ses_info->st_ses.capture_handle == capture_handle)
238 return st_ses_info;
239 }
240 return NULL;
241}
242
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530243static int populate_usecase(struct audio_hal_usecase *usecase,
244 struct audio_usecase *uc_info)
245{
246 int status = 0;
247
248 switch(uc_info->type) {
249 case PCM_PLAYBACK:
250 if (uc_info->id == USECASE_AUDIO_PLAYBACK_VOIP)
251 usecase->type = USECASE_TYPE_VOIP_CALL;
252 else
253 usecase->type = USECASE_TYPE_PCM_PLAYBACK;
254 break;
255
256 case PCM_CAPTURE:
257 if (uc_info->id == USECASE_AUDIO_RECORD_VOIP)
258 usecase->type = USECASE_TYPE_VOIP_CALL;
259 else
260 usecase->type = USECASE_TYPE_PCM_CAPTURE;
261 break;
262
263 case VOICE_CALL:
264 usecase->type = USECASE_TYPE_VOICE_CALL;
265 break;
266
267 default:
268 ALOGE("%s: unsupported usecase type %d", __func__, uc_info->type);
269 status = -EINVAL;
270 }
271 return status;
272}
273
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530274static void stdev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
275{
Derek Chen6f293672019-04-01 01:40:24 -0700276 audio_event_info_t event;
277 char value[32];
278 int ret = 0;
279
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530280 if (!parms)
281 return;
282
Derek Chen6f293672019-04-01 01:40:24 -0700283 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value,
284 sizeof(value));
285 if (ret > 0) {
286 if (strstr(value, "OFFLINE")) {
287 event.u.status = SND_CARD_STATUS_OFFLINE;
288 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
289 }
290 else if (strstr(value, "ONLINE")) {
291 event.u.status = SND_CARD_STATUS_ONLINE;
292 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
293 }
294 else
295 ALOGE("%s: unknown snd_card_status", __func__);
296 }
297
298 ret = str_parms_get_str(parms, "CPE_STATUS", value, sizeof(value));
299 if (ret > 0) {
300 if (strstr(value, "OFFLINE")) {
301 event.u.status = CPE_STATUS_OFFLINE;
302 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
303 }
304 else if (strstr(value, "ONLINE")) {
305 event.u.status = CPE_STATUS_ONLINE;
306 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
307 }
308 else
309 ALOGE("%s: unknown CPE status", __func__);
310 }
311
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530312 return;
313}
314
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700315int audio_hw_call_back(sound_trigger_event_type_t event,
316 sound_trigger_event_info_t* config)
317{
318 int status = 0;
319 struct sound_trigger_info *st_ses_info;
320
321 if (!st_dev)
322 return -EINVAL;
323
324 pthread_mutex_lock(&st_dev->lock);
325 switch (event) {
326 case ST_EVENT_SESSION_REGISTER:
327 if (!config) {
328 ALOGE("%s: NULL config", __func__);
329 status = -EINVAL;
330 break;
331 }
332 st_ses_info= calloc(1, sizeof(struct sound_trigger_info ));
333 if (!st_ses_info) {
334 ALOGE("%s: st_ses_info alloc failed", __func__);
335 status = -ENOMEM;
336 break;
337 }
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700338 memcpy(&st_ses_info->st_ses, &config->st_ses, sizeof (struct sound_trigger_session_info));
339 ALOGV("%s: add capture_handle %d st session opaque ptr %p", __func__,
340 st_ses_info->st_ses.capture_handle, st_ses_info->st_ses.p_ses);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700341 list_add_tail(&st_dev->st_ses_list, &st_ses_info->list);
342 break;
343
Surendar Karka59c51072017-12-13 11:25:57 +0530344 case ST_EVENT_START_KEEP_ALIVE:
345 pthread_mutex_unlock(&st_dev->lock);
346 pthread_mutex_lock(&st_dev->adev->lock);
347 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
348 pthread_mutex_unlock(&st_dev->adev->lock);
349 goto done;
350
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700351 case ST_EVENT_SESSION_DEREGISTER:
352 if (!config) {
353 ALOGE("%s: NULL config", __func__);
354 status = -EINVAL;
355 break;
356 }
357 st_ses_info = get_sound_trigger_info(config->st_ses.capture_handle);
358 if (!st_ses_info) {
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700359 ALOGE("%s: st session opaque ptr %p not in the list!", __func__, config->st_ses.p_ses);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700360 status = -EINVAL;
361 break;
362 }
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700363 ALOGV("%s: remove capture_handle %d st session opaque ptr %p", __func__,
364 st_ses_info->st_ses.capture_handle, st_ses_info->st_ses.p_ses);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700365 list_remove(&st_ses_info->list);
366 free(st_ses_info);
367 break;
Surendar Karka59c51072017-12-13 11:25:57 +0530368
369 case ST_EVENT_STOP_KEEP_ALIVE:
370 pthread_mutex_unlock(&st_dev->lock);
371 pthread_mutex_lock(&st_dev->adev->lock);
372 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
373 pthread_mutex_unlock(&st_dev->adev->lock);
374 goto done;
375
kunleiz70e57612018-12-28 17:50:23 +0800376 case ST_EVENT_UPDATE_ECHO_REF:
377 if (!config) {
378 ALOGE("%s: NULL config", __func__);
379 status = -EINVAL;
380 break;
381 }
382 st_dev->st_ec_ref_enabled = config->st_ec_ref_enabled;
383 break;
384
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700385 default:
386 ALOGW("%s: Unknown event %d", __func__, event);
387 break;
388 }
389 pthread_mutex_unlock(&st_dev->lock);
Surendar Karka59c51072017-12-13 11:25:57 +0530390done:
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700391 return status;
392}
393
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700394int audio_extn_sound_trigger_read(struct stream_in *in, void *buffer,
395 size_t bytes)
396{
397 int ret = -1;
398 struct sound_trigger_info *st_info = NULL;
399 audio_event_info_t event;
400
401 if (!st_dev)
402 return ret;
403
404 if (!in->is_st_session_active) {
405 ALOGE(" %s: Sound trigger is not active", __func__);
406 goto exit;
407 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700408
409 pthread_mutex_lock(&st_dev->lock);
410 st_info = get_sound_trigger_info(in->capture_handle);
411 pthread_mutex_unlock(&st_dev->lock);
412 if (st_info) {
413 event.u.aud_info.ses_info = &st_info->st_ses;
414 event.u.aud_info.buf = buffer;
415 event.u.aud_info.num_bytes = bytes;
416 ret = st_dev->st_callback(AUDIO_EVENT_READ_SAMPLES, &event);
417 }
418
419exit:
420 if (ret) {
421 if (-ENETRESET == ret)
422 in->is_st_session_active = false;
423 memset(buffer, 0, bytes);
424 ALOGV("%s: read failed status %d - sleep", __func__, ret);
425 usleep((bytes * 1000000) / (audio_stream_in_frame_size((struct audio_stream_in *)in) *
426 in->config.rate));
427 }
428 return ret;
429}
430
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700431void audio_extn_sound_trigger_stop_lab(struct stream_in *in)
432{
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700433 struct sound_trigger_info *st_ses_info = NULL;
434 audio_event_info_t event;
435
Mingming Yinfd7607b2016-01-22 12:48:44 -0800436 if (!st_dev || !in || !in->is_st_session_active)
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700437 return;
438
439 pthread_mutex_lock(&st_dev->lock);
440 st_ses_info = get_sound_trigger_info(in->capture_handle);
Bharath Ramachandramurthy5baa6a52014-10-21 11:18:49 -0700441 pthread_mutex_unlock(&st_dev->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700442 if (st_ses_info) {
443 event.u.ses_info = st_ses_info->st_ses;
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700444 ALOGV("%s: AUDIO_EVENT_STOP_LAB st sess %p", __func__, st_ses_info->st_ses.p_ses);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700445 st_dev->st_callback(AUDIO_EVENT_STOP_LAB, &event);
Mingming Yinfd7607b2016-01-22 12:48:44 -0800446 in->is_st_session_active = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700447 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700448}
449void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in)
450{
451 struct sound_trigger_info *st_ses_info = NULL;
452 struct listnode *node;
453
454 if (!st_dev || !in)
455 return;
456
457 pthread_mutex_lock(&st_dev->lock);
458 in->is_st_session = false;
459 ALOGV("%s: list %d capture_handle %d", __func__,
460 list_empty(&st_dev->st_ses_list), in->capture_handle);
461 list_for_each(node, &st_dev->st_ses_list) {
462 st_ses_info = node_to_item(node, struct sound_trigger_info , list);
463 if (st_ses_info->st_ses.capture_handle == in->capture_handle) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700464 in->config = st_ses_info->st_ses.config;
465 in->channel_mask = audio_channel_in_mask_from_count(in->config.channels);
466 in->is_st_session = true;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -0800467 in->is_st_session_active = true;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700468 ALOGD("%s: capture_handle %d is sound trigger", __func__, in->capture_handle);
469 break;
470 }
471 }
472 pthread_mutex_unlock(&st_dev->lock);
473}
474
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530475bool is_same_as_st_device(snd_device_t snd_device)
476{
477 if (snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC ||
478 snd_device == SND_DEVICE_IN_HANDSET_MIC ||
479 snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC_NS ||
480 snd_device == SND_DEVICE_IN_SPEAKER_MIC ||
481 snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC ||
482 snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC ||
483 snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC_NS ||
484 snd_device == SND_DEVICE_IN_SPEAKER_MIC_NS) {
485 ALOGD("audio HAL using same device %d as ST", snd_device);
486 return true;
487 }
488 return false;
489}
490
kunleiz70e57612018-12-28 17:50:23 +0800491bool audio_extn_sound_trigger_check_ec_ref_enable()
492{
493 bool ret = false;
494
495 if (!st_dev) {
496 ALOGE("%s: st_dev NULL", __func__);
497 return ret;
498 }
499
500 pthread_mutex_lock(&st_dev->lock);
501 if (st_dev->st_ec_ref_enabled) {
502 ret = true;
503 ALOGD("%s: EC Reference is enabled", __func__);
504 } else {
505 ALOGD("%s: EC Reference is disabled", __func__);
506 }
507 pthread_mutex_unlock(&st_dev->lock);
508
509 return ret;
510}
511
512void audio_extn_sound_trigger_update_ec_ref_status(bool on)
513{
514 struct audio_event_info ev_info;
515
516 if (!st_dev) {
517 ALOGE("%s: st_dev NULL", __func__);
518 return;
519 }
520
521 ev_info.u.audio_ec_ref_enabled = on;
522 st_dev->st_callback(AUDIO_EVENT_UPDATE_ECHO_REF, &ev_info);
523 ALOGD("%s: update audio echo ref status %s",__func__,
524 ev_info.u.audio_ec_ref_enabled == true ? "true" : "false");
525}
526
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700527void audio_extn_sound_trigger_update_device_status(snd_device_t snd_device,
528 st_event_type_t event)
529{
530 bool raise_event = false;
531 int device_type = -1;
532
533 if (!st_dev)
534 return;
535
536 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
537 snd_device < SND_DEVICE_OUT_END)
538 device_type = PCM_PLAYBACK;
539 else if (snd_device >= SND_DEVICE_IN_BEGIN &&
540 snd_device < SND_DEVICE_IN_END)
541 device_type = PCM_CAPTURE;
542 else {
543 ALOGE("%s: invalid device 0x%x, for event %d",
544 __func__, snd_device, event);
545 return;
546 }
547
548 raise_event = platform_sound_trigger_device_needs_event(snd_device);
549 ALOGI("%s: device 0x%x of type %d for Event %d, with Raise=%d",
550 __func__, snd_device, device_type, event, raise_event);
551 if (raise_event && (device_type == PCM_CAPTURE)) {
552 switch(event) {
553 case ST_EVENT_SND_DEVICE_FREE:
554 st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, NULL);
555 break;
556 case ST_EVENT_SND_DEVICE_BUSY:
557 st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE, NULL);
558 break;
559 default:
560 ALOGW("%s:invalid event %d for device 0x%x",
561 __func__, event, snd_device);
562 }
563 }/*Events for output device, if required can be placed here in else*/
564}
565
566void audio_extn_sound_trigger_update_stream_status(struct audio_usecase *uc_info,
567 st_event_type_t event)
568{
569 bool raise_event = false;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530570 struct audio_event_info ev_info;
571 audio_event_type_t ev;
572 /*Initialize to invalid device*/
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800573 list_init(&ev_info.device_info.devices);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700574
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530575 if (!st_dev)
576 return;
577
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700578 if (uc_info == NULL) {
579 ALOGE("%s: usecase is NULL!!!", __func__);
580 return;
581 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700582
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530583 if ((uc_info->in_snd_device >= SND_DEVICE_IN_BEGIN &&
584 uc_info->in_snd_device < SND_DEVICE_IN_END)) {
585 if (is_same_as_st_device(uc_info->in_snd_device))
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800586 update_device_list(&ev_info.device_info.devices, ST_DEVICE_HANDSET_MIC, "", true);
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530587 } else {
588 ALOGE("%s: invalid input device 0x%x, for event %d",
589 __func__, uc_info->in_snd_device, event);
590 }
591 raise_event = platform_sound_trigger_usecase_needs_event(uc_info->id);
592 ALOGD("%s: uc_info->id %d of type %d for Event %d, with Raise=%d",
593 __func__, uc_info->id, uc_info->type, event, raise_event);
594 if (raise_event) {
595 if (uc_info->type == PCM_PLAYBACK) {
Zhou Songc1088ea2018-06-12 00:17:29 +0800596 if (uc_info->stream.out)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800597 assign_devices(&ev_info.device_info.devices, &uc_info->stream.out->device_list);
Zhou Songc1088ea2018-06-12 00:17:29 +0800598 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800599 reassign_device_list(&ev_info.device_info.devices,
600 AUDIO_DEVICE_OUT_SPEAKER, "");
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530601 switch(event) {
602 case ST_EVENT_STREAM_FREE:
Zhou Songc1088ea2018-06-12 00:17:29 +0800603 st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE, &ev_info);
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530604 break;
605 case ST_EVENT_STREAM_BUSY:
Zhou Songc1088ea2018-06-12 00:17:29 +0800606 st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE, &ev_info);
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530607 break;
608 default:
609 ALOGW("%s:invalid event %d, for usecase %d",
610 __func__, event, uc_info->id);
611 }
Revathi Uddaraju9f99ddd2018-05-03 12:01:38 +0530612 } else if ((uc_info->type == PCM_CAPTURE) || (uc_info->type == VOICE_CALL)) {
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530613 if (event == ST_EVENT_STREAM_BUSY)
614 ev = AUDIO_EVENT_CAPTURE_STREAM_ACTIVE;
615 else
616 ev = AUDIO_EVENT_CAPTURE_STREAM_INACTIVE;
617 if (!populate_usecase(&ev_info.u.usecase, uc_info)) {
618 ALOGD("%s: send event %d: usecase id %d, type %d",
619 __func__, ev, uc_info->id, uc_info->type);
620 st_dev->st_callback(ev, &ev_info);
621 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700622 }
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530623 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700624}
625
Zhou Songc1088ea2018-06-12 00:17:29 +0800626void audio_extn_sound_trigger_update_battery_status(bool charging)
627{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800628 struct audio_event_info ev_info = {{0}, {0}};
Zhou Songc1088ea2018-06-12 00:17:29 +0800629
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800630 if (!st_dev)
Zhou Songc1088ea2018-06-12 00:17:29 +0800631 return;
632
633 ev_info.u.value = charging;
634 st_dev->st_callback(AUDIO_EVENT_BATTERY_STATUS_CHANGED, &ev_info);
635}
636
Quinn Male70f20f32019-06-26 16:50:26 -0700637void audio_extn_sound_trigger_update_screen_status(bool screen_off)
638{
639 struct audio_event_info ev_info = {{0}, {0}};
640
641 if (!st_dev)
642 return;
643
644 ev_info.u.value = screen_off;
645 st_dev->st_callback(AUDIO_EVENT_SCREEN_STATUS_CHANGED, &ev_info);
646}
647
Zhou Songc1088ea2018-06-12 00:17:29 +0800648
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700649void audio_extn_sound_trigger_set_parameters(struct audio_device *adev __unused,
650 struct str_parms *params)
651{
652 audio_event_info_t event;
653 char value[32];
Bharath Ramachandramurthyc694f8a2014-09-25 16:15:12 -0700654 int ret, val;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700655
656 if(!st_dev || !params) {
657 ALOGE("%s: str_params NULL", __func__);
658 return;
659 }
660
Derek Chen6f293672019-04-01 01:40:24 -0700661 stdev_snd_mon_cb(NULL, params);
Bharath Ramachandramurthyc694f8a2014-09-25 16:15:12 -0700662
663 ret = str_parms_get_int(params, "SVA_NUM_SESSIONS", &val);
664 if (ret >= 0) {
665 event.u.value = val;
666 st_dev->st_callback(AUDIO_EVENT_NUM_ST_SESSIONS, &event);
667 }
Quinn male73dd1fd2016-12-02 10:47:11 -0800668
669 ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_CONNECT, &val);
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +0530670 if ((ret >= 0) && (audio_is_input_device(val) ||
671 (val == AUDIO_DEVICE_OUT_LINE))) {
Quinn male73dd1fd2016-12-02 10:47:11 -0800672 event.u.value = val;
673 st_dev->st_callback(AUDIO_EVENT_DEVICE_CONNECT, &event);
674 }
675
676 ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_DISCONNECT, &val);
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +0530677 if ((ret >= 0) && (audio_is_input_device(val) ||
678 (val == AUDIO_DEVICE_OUT_LINE))) {
Quinn male73dd1fd2016-12-02 10:47:11 -0800679 event.u.value = val;
680 st_dev->st_callback(AUDIO_EVENT_DEVICE_DISCONNECT, &event);
681 }
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530682
683 ret = str_parms_get_str(params, "SVA_EXEC_MODE", value, sizeof(value));
684 if (ret >= 0) {
685 strlcpy(event.u.str_value, value, sizeof(event.u.str_value));
686 st_dev->st_callback(AUDIO_EVENT_SVA_EXEC_MODE, &event);
687 }
Aalique Grahame22e49102018-12-18 14:23:57 -0800688
689 ret = str_parms_get_str(params, "SLPI_STATUS", value, sizeof(value));
690 if (ret > 0) {
691 if (strstr(value, "OFFLINE")) {
692 event.u.status = SLPI_STATUS_OFFLINE;
693 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
694 } else if (strstr(value, "ONLINE")) {
695 event.u.status = SLPI_STATUS_ONLINE;
696 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
697 } else
698 ALOGE("%s: unknown SLPI status", __func__);
699 }
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530700}
701
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530702static int extract_sm_handle(const char *keys, char *paramstr) {
703 char *tmpstr, *token;
704 char *inputstr = NULL;
705 int value = -EINVAL;
706
707 if (keys == NULL || paramstr == NULL)
708 goto exit;
709
710 inputstr = strdup(keys);
711 token =strtok_r(inputstr,":", &tmpstr);
712
713 if (token == NULL)
714 goto exit;
715
716 ALOGD("%s input string <%s> param string <%s>", __func__, keys,token);
717 strlcpy(paramstr, token, MAX_STR_LENGTH_FFV_PARAMS);
718 token =strtok_r(NULL,":=",&tmpstr);
719
720 if (token == NULL)
721 goto exit;
722
723 value = atoi(token);
724 if (value > 0 && value < MAX_FFV_SESSION_ID)
725 ALOGD(" %s SVA sm handle<=%d>",__func__, value);
726
727exit:
728 if (inputstr != NULL)
729 free(inputstr);
730
731 return value;
732}
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530733void audio_extn_sound_trigger_get_parameters(const struct audio_device *adev __unused,
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530734 struct str_parms *query,
735 struct str_parms *reply)
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530736{
737 audio_event_info_t event;
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530738 int ret;
739 char value[32], paramstr[MAX_STR_LENGTH_FFV_PARAMS];
740
741 ALOGD("%s input string<%s>", __func__, str_parms_to_str(query));
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530742
743 ret = str_parms_get_str(query, "SVA_EXEC_MODE_STATUS", value,
744 sizeof(value));
745 if (ret >= 0) {
746 st_dev->st_callback(AUDIO_EVENT_SVA_EXEC_MODE_STATUS, &event);
747 str_parms_add_int(reply, "SVA_EXEC_MODE_STATUS", event.u.value);
748 }
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530749
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530750 ret = extract_sm_handle(str_parms_to_str(query), paramstr);
751
752 if ((ret >= 0) && !strncmp(paramstr, SVA_PARAM_DIRECTION_OF_ARRIVAL,
753 MAX_STR_LENGTH_FFV_PARAMS)) {
754 event.u.st_get_param_data.sm_handle = ret;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530755 event.u.st_get_param_data.param = SVA_PARAM_DIRECTION_OF_ARRIVAL;
756 event.u.st_get_param_data.reply = reply;
757 st_dev->st_callback(AUDIO_EVENT_GET_PARAM, &event);
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530758 } else if ((ret >=0) && !strncmp(paramstr, SVA_PARAM_CHANNEL_INDEX,
759 MAX_STR_LENGTH_FFV_PARAMS)) {
760 event.u.st_get_param_data.sm_handle = ret;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530761 event.u.st_get_param_data.param = SVA_PARAM_CHANNEL_INDEX;
762 event.u.st_get_param_data.reply = reply;
763 st_dev->st_callback(AUDIO_EVENT_GET_PARAM, &event);
764 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700765}
766
767int audio_extn_sound_trigger_init(struct audio_device *adev)
768{
769 int status = 0;
770 char sound_trigger_lib[100];
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530771 void *sthal_prop_api_version;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700772
773 ALOGI("%s: Enter", __func__);
774
775 st_dev = (struct sound_trigger_audio_device*)
776 calloc(1, sizeof(struct sound_trigger_audio_device));
777 if (!st_dev) {
778 ALOGE("%s: ERROR. sound trigger alloc failed", __func__);
779 return -ENOMEM;
780 }
781
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530782 get_library_path(sound_trigger_lib);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700783 st_dev->lib_handle = dlopen(sound_trigger_lib, RTLD_NOW);
784
785 if (st_dev->lib_handle == NULL) {
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530786 ALOGE("%s: error %s", __func__, dlerror());
787 status = -ENODEV;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700788 goto cleanup;
789 }
790 ALOGI("%s: DLOPEN successful for %s", __func__, sound_trigger_lib);
791
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530792 DLSYM(st_dev->lib_handle, st_dev->st_callback, sound_trigger_hw_call_back,
793 status);
794 if (status)
795 goto cleanup;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700796
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530797 DLSYM(st_dev->lib_handle, sthal_prop_api_version,
798 sthal_prop_api_version, status);
799 if (status) {
800 st_dev->sthal_prop_api_version = 0;
801 status = 0; /* passthru for backward compability */
802 } else {
Jhansi Konathala902fc412018-09-05 13:21:44 +0530803 if (sthal_prop_api_version != NULL) {
804 st_dev->sthal_prop_api_version = *(int*)sthal_prop_api_version;
805 }
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530806 if (MAJOR_VERSION(st_dev->sthal_prop_api_version) !=
807 MAJOR_VERSION(STHAL_PROP_API_CURRENT_VERSION)) {
808 ALOGE("%s: Incompatible API versions ahal:0x%x != sthal:0x%x",
809 __func__, STHAL_PROP_API_CURRENT_VERSION,
810 st_dev->sthal_prop_api_version);
811 goto cleanup;
812 }
813 ALOGD("%s: sthal is using proprietary API version 0x%04x", __func__,
814 st_dev->sthal_prop_api_version);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700815 }
816
817 st_dev->adev = adev;
kunleiz70e57612018-12-28 17:50:23 +0800818 st_dev->st_ec_ref_enabled = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700819 list_init(&st_dev->st_ses_list);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530820 audio_extn_snd_mon_register_listener(st_dev, stdev_snd_mon_cb);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700821
822 return 0;
823
824cleanup:
825 if (st_dev->lib_handle)
826 dlclose(st_dev->lib_handle);
827 free(st_dev);
828 st_dev = NULL;
829 return status;
830
831}
832
833void audio_extn_sound_trigger_deinit(struct audio_device *adev)
834{
835 ALOGI("%s: Enter", __func__);
836 if (st_dev && (st_dev->adev == adev) && st_dev->lib_handle) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530837 audio_extn_snd_mon_unregister_listener(st_dev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700838 dlclose(st_dev->lib_handle);
839 free(st_dev);
840 st_dev = NULL;
841 }
842}