blob: 5d6624d072a514a7c954082a5cffdb3f3a53e6a1 [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
Jasmine Cha20b15f92019-05-17 20:56:43 +0800189
190#define ST_DEVICE SND_DEVICE_IN_HANDSET_MIC
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530191/*
192 * Current proprietary API version used by AHAL. Queried by STHAL
193 * for compatibility check with AHAL
194 */
195const unsigned int sthal_prop_api_version = STHAL_PROP_API_CURRENT_VERSION;
196
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700197struct sound_trigger_info {
198 struct sound_trigger_session_info st_ses;
199 bool lab_stopped;
200 struct listnode list;
201};
202
203struct sound_trigger_audio_device {
204 void *lib_handle;
205 struct audio_device *adev;
206 sound_trigger_hw_call_back_t st_callback;
207 struct listnode st_ses_list;
208 pthread_mutex_t lock;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530209 unsigned int sthal_prop_api_version;
kunleiz70e57612018-12-28 17:50:23 +0800210 bool st_ec_ref_enabled;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700211};
212
213static struct sound_trigger_audio_device *st_dev;
214
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530215#if LINUX_ENABLED
216static void get_library_path(char *lib_path)
217{
218 snprintf(lib_path, MAX_LIBRARY_PATH,
Manish Dewangan6a36d002017-10-09 14:11:00 +0530219 "sound_trigger.primary.default.so");
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530220}
221#else
222static void get_library_path(char *lib_path)
223{
224 snprintf(lib_path, MAX_LIBRARY_PATH,
David Ng06ccd872017-03-15 11:39:33 -0700225 "/vendor/lib/hw/sound_trigger.primary.%s.so",
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530226 XSTR(SOUND_TRIGGER_PLATFORM_NAME));
227}
228#endif
229
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700230static struct sound_trigger_info *
231get_sound_trigger_info(int capture_handle)
232{
233 struct sound_trigger_info *st_ses_info = NULL;
234 struct listnode *node;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700235 ALOGV("%s: list empty %d capture_handle %d", __func__,
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700236 list_empty(&st_dev->st_ses_list), capture_handle);
237 list_for_each(node, &st_dev->st_ses_list) {
238 st_ses_info = node_to_item(node, struct sound_trigger_info , list);
239 if (st_ses_info->st_ses.capture_handle == capture_handle)
240 return st_ses_info;
241 }
242 return NULL;
243}
244
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530245static int populate_usecase(struct audio_hal_usecase *usecase,
246 struct audio_usecase *uc_info)
247{
248 int status = 0;
249
250 switch(uc_info->type) {
251 case PCM_PLAYBACK:
252 if (uc_info->id == USECASE_AUDIO_PLAYBACK_VOIP)
253 usecase->type = USECASE_TYPE_VOIP_CALL;
254 else
255 usecase->type = USECASE_TYPE_PCM_PLAYBACK;
256 break;
257
258 case PCM_CAPTURE:
Jasmine Cha20b15f92019-05-17 20:56:43 +0800259 if (uc_info->stream.in != NULL &&
260 uc_info->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530261 usecase->type = USECASE_TYPE_VOIP_CALL;
262 else
263 usecase->type = USECASE_TYPE_PCM_CAPTURE;
264 break;
265
266 case VOICE_CALL:
267 usecase->type = USECASE_TYPE_VOICE_CALL;
268 break;
269
270 default:
271 ALOGE("%s: unsupported usecase type %d", __func__, uc_info->type);
272 status = -EINVAL;
273 }
274 return status;
275}
276
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530277static void stdev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
278{
Derek Chen6f293672019-04-01 01:40:24 -0700279 audio_event_info_t event;
280 char value[32];
281 int ret = 0;
282
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530283 if (!parms)
284 return;
285
Derek Chen6f293672019-04-01 01:40:24 -0700286 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value,
287 sizeof(value));
288 if (ret > 0) {
289 if (strstr(value, "OFFLINE")) {
290 event.u.status = SND_CARD_STATUS_OFFLINE;
291 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
292 }
293 else if (strstr(value, "ONLINE")) {
294 event.u.status = SND_CARD_STATUS_ONLINE;
295 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
296 }
297 else
298 ALOGE("%s: unknown snd_card_status", __func__);
299 }
300
301 ret = str_parms_get_str(parms, "CPE_STATUS", value, sizeof(value));
302 if (ret > 0) {
303 if (strstr(value, "OFFLINE")) {
304 event.u.status = CPE_STATUS_OFFLINE;
305 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
306 }
307 else if (strstr(value, "ONLINE")) {
308 event.u.status = CPE_STATUS_ONLINE;
309 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
310 }
311 else
312 ALOGE("%s: unknown CPE status", __func__);
313 }
314
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530315 return;
316}
317
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700318int audio_hw_call_back(sound_trigger_event_type_t event,
319 sound_trigger_event_info_t* config)
320{
321 int status = 0;
322 struct sound_trigger_info *st_ses_info;
323
324 if (!st_dev)
325 return -EINVAL;
326
327 pthread_mutex_lock(&st_dev->lock);
328 switch (event) {
329 case ST_EVENT_SESSION_REGISTER:
330 if (!config) {
331 ALOGE("%s: NULL config", __func__);
332 status = -EINVAL;
333 break;
334 }
335 st_ses_info= calloc(1, sizeof(struct sound_trigger_info ));
336 if (!st_ses_info) {
337 ALOGE("%s: st_ses_info alloc failed", __func__);
338 status = -ENOMEM;
339 break;
340 }
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700341 memcpy(&st_ses_info->st_ses, &config->st_ses, sizeof (struct sound_trigger_session_info));
342 ALOGV("%s: add capture_handle %d st session opaque ptr %p", __func__,
343 st_ses_info->st_ses.capture_handle, st_ses_info->st_ses.p_ses);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700344 list_add_tail(&st_dev->st_ses_list, &st_ses_info->list);
345 break;
346
Surendar Karka59c51072017-12-13 11:25:57 +0530347 case ST_EVENT_START_KEEP_ALIVE:
348 pthread_mutex_unlock(&st_dev->lock);
349 pthread_mutex_lock(&st_dev->adev->lock);
350 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
351 pthread_mutex_unlock(&st_dev->adev->lock);
352 goto done;
353
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700354 case ST_EVENT_SESSION_DEREGISTER:
355 if (!config) {
356 ALOGE("%s: NULL config", __func__);
357 status = -EINVAL;
358 break;
359 }
360 st_ses_info = get_sound_trigger_info(config->st_ses.capture_handle);
361 if (!st_ses_info) {
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700362 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 -0700363 status = -EINVAL;
364 break;
365 }
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700366 ALOGV("%s: remove capture_handle %d st session opaque ptr %p", __func__,
367 st_ses_info->st_ses.capture_handle, st_ses_info->st_ses.p_ses);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700368 list_remove(&st_ses_info->list);
369 free(st_ses_info);
370 break;
Surendar Karka59c51072017-12-13 11:25:57 +0530371
372 case ST_EVENT_STOP_KEEP_ALIVE:
373 pthread_mutex_unlock(&st_dev->lock);
374 pthread_mutex_lock(&st_dev->adev->lock);
375 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
376 pthread_mutex_unlock(&st_dev->adev->lock);
377 goto done;
378
kunleiz70e57612018-12-28 17:50:23 +0800379 case ST_EVENT_UPDATE_ECHO_REF:
380 if (!config) {
381 ALOGE("%s: NULL config", __func__);
382 status = -EINVAL;
383 break;
384 }
385 st_dev->st_ec_ref_enabled = config->st_ec_ref_enabled;
386 break;
387
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700388 default:
389 ALOGW("%s: Unknown event %d", __func__, event);
390 break;
391 }
392 pthread_mutex_unlock(&st_dev->lock);
Surendar Karka59c51072017-12-13 11:25:57 +0530393done:
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700394 return status;
395}
396
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700397int audio_extn_sound_trigger_read(struct stream_in *in, void *buffer,
398 size_t bytes)
399{
400 int ret = -1;
401 struct sound_trigger_info *st_info = NULL;
402 audio_event_info_t event;
403
404 if (!st_dev)
405 return ret;
406
407 if (!in->is_st_session_active) {
408 ALOGE(" %s: Sound trigger is not active", __func__);
409 goto exit;
410 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700411
412 pthread_mutex_lock(&st_dev->lock);
413 st_info = get_sound_trigger_info(in->capture_handle);
414 pthread_mutex_unlock(&st_dev->lock);
415 if (st_info) {
416 event.u.aud_info.ses_info = &st_info->st_ses;
417 event.u.aud_info.buf = buffer;
418 event.u.aud_info.num_bytes = bytes;
419 ret = st_dev->st_callback(AUDIO_EVENT_READ_SAMPLES, &event);
420 }
421
422exit:
423 if (ret) {
424 if (-ENETRESET == ret)
425 in->is_st_session_active = false;
426 memset(buffer, 0, bytes);
427 ALOGV("%s: read failed status %d - sleep", __func__, ret);
Shalini Manjunatha4ed29802021-06-11 17:07:02 +0530428 usleep(((useconds_t)bytes * 1000000) / (audio_stream_in_frame_size((struct audio_stream_in *)in) *
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700429 in->config.rate));
430 }
431 return ret;
432}
433
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700434void audio_extn_sound_trigger_stop_lab(struct stream_in *in)
435{
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700436 struct sound_trigger_info *st_ses_info = NULL;
437 audio_event_info_t event;
438
Mingming Yinfd7607b2016-01-22 12:48:44 -0800439 if (!st_dev || !in || !in->is_st_session_active)
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700440 return;
441
442 pthread_mutex_lock(&st_dev->lock);
443 st_ses_info = get_sound_trigger_info(in->capture_handle);
Bharath Ramachandramurthy5baa6a52014-10-21 11:18:49 -0700444 pthread_mutex_unlock(&st_dev->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700445 if (st_ses_info) {
446 event.u.ses_info = st_ses_info->st_ses;
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700447 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 -0700448 st_dev->st_callback(AUDIO_EVENT_STOP_LAB, &event);
Mingming Yinfd7607b2016-01-22 12:48:44 -0800449 in->is_st_session_active = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700450 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700451}
452void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in)
453{
454 struct sound_trigger_info *st_ses_info = NULL;
455 struct listnode *node;
456
457 if (!st_dev || !in)
458 return;
459
460 pthread_mutex_lock(&st_dev->lock);
461 in->is_st_session = false;
462 ALOGV("%s: list %d capture_handle %d", __func__,
463 list_empty(&st_dev->st_ses_list), in->capture_handle);
464 list_for_each(node, &st_dev->st_ses_list) {
465 st_ses_info = node_to_item(node, struct sound_trigger_info , list);
466 if (st_ses_info->st_ses.capture_handle == in->capture_handle) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700467 in->config = st_ses_info->st_ses.config;
468 in->channel_mask = audio_channel_in_mask_from_count(in->config.channels);
469 in->is_st_session = true;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -0800470 in->is_st_session_active = true;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700471 ALOGD("%s: capture_handle %d is sound trigger", __func__, in->capture_handle);
472 break;
473 }
474 }
475 pthread_mutex_unlock(&st_dev->lock);
476}
477
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530478bool is_same_as_st_device(snd_device_t snd_device)
479{
Jasmine Cha20b15f92019-05-17 20:56:43 +0800480 if (platform_check_all_backends_match(ST_DEVICE, snd_device)) {
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530481 ALOGD("audio HAL using same device %d as ST", snd_device);
482 return true;
483 }
484 return false;
485}
486
kunleiz70e57612018-12-28 17:50:23 +0800487bool audio_extn_sound_trigger_check_ec_ref_enable()
488{
489 bool ret = false;
490
491 if (!st_dev) {
492 ALOGE("%s: st_dev NULL", __func__);
493 return ret;
494 }
495
496 pthread_mutex_lock(&st_dev->lock);
497 if (st_dev->st_ec_ref_enabled) {
498 ret = true;
499 ALOGD("%s: EC Reference is enabled", __func__);
500 } else {
501 ALOGD("%s: EC Reference is disabled", __func__);
502 }
503 pthread_mutex_unlock(&st_dev->lock);
504
505 return ret;
506}
507
508void audio_extn_sound_trigger_update_ec_ref_status(bool on)
509{
510 struct audio_event_info ev_info;
511
512 if (!st_dev) {
513 ALOGE("%s: st_dev NULL", __func__);
514 return;
515 }
516
517 ev_info.u.audio_ec_ref_enabled = on;
518 st_dev->st_callback(AUDIO_EVENT_UPDATE_ECHO_REF, &ev_info);
519 ALOGD("%s: update audio echo ref status %s",__func__,
520 ev_info.u.audio_ec_ref_enabled == true ? "true" : "false");
521}
522
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700523void audio_extn_sound_trigger_update_device_status(snd_device_t snd_device,
524 st_event_type_t event)
525{
526 bool raise_event = false;
527 int device_type = -1;
Jasmine Cha20b15f92019-05-17 20:56:43 +0800528 struct audio_event_info ev_info;
529
530 ev_info.u.usecase.type = -1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700531
532 if (!st_dev)
533 return;
534
Jasmine Cha20b15f92019-05-17 20:56:43 +0800535 list_init(&ev_info.device_info.devices);
536
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700537 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
538 snd_device < SND_DEVICE_OUT_END)
539 device_type = PCM_PLAYBACK;
540 else if (snd_device >= SND_DEVICE_IN_BEGIN &&
Jasmine Cha20b15f92019-05-17 20:56:43 +0800541 snd_device < SND_DEVICE_IN_END) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700542 device_type = PCM_CAPTURE;
Jasmine Cha20b15f92019-05-17 20:56:43 +0800543 if (is_same_as_st_device(snd_device))
544 update_device_list(&ev_info.device_info.devices, ST_DEVICE_HANDSET_MIC, "", true);
545 } else {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700546 ALOGE("%s: invalid device 0x%x, for event %d",
547 __func__, snd_device, event);
548 return;
549 }
550
Jasmine Cha20b15f92019-05-17 20:56:43 +0800551 struct stream_in *active_input = adev_get_active_input(st_dev->adev);
552 audio_source_t source = (active_input == NULL) ?
553 AUDIO_SOURCE_DEFAULT : active_input->source;
554 if (st_dev->adev->mode == AUDIO_MODE_IN_CALL) {
555 ev_info.u.usecase.type = USECASE_TYPE_VOICE_CALL;
556 } else if ((st_dev->adev->mode == AUDIO_MODE_IN_COMMUNICATION ||
557 source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
558 active_input) {
559 ev_info.u.usecase.type = USECASE_TYPE_VOIP_CALL;
560 } else if (device_type == PCM_CAPTURE) {
561 ev_info.u.usecase.type = USECASE_TYPE_PCM_CAPTURE;
562 }
563
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700564 raise_event = platform_sound_trigger_device_needs_event(snd_device);
565 ALOGI("%s: device 0x%x of type %d for Event %d, with Raise=%d",
566 __func__, snd_device, device_type, event, raise_event);
567 if (raise_event && (device_type == PCM_CAPTURE)) {
568 switch(event) {
569 case ST_EVENT_SND_DEVICE_FREE:
Jasmine Cha20b15f92019-05-17 20:56:43 +0800570 st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, &ev_info);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700571 break;
572 case ST_EVENT_SND_DEVICE_BUSY:
Jasmine Cha20b15f92019-05-17 20:56:43 +0800573 st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE, &ev_info);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700574 break;
575 default:
576 ALOGW("%s:invalid event %d for device 0x%x",
577 __func__, event, snd_device);
578 }
579 }/*Events for output device, if required can be placed here in else*/
580}
581
582void audio_extn_sound_trigger_update_stream_status(struct audio_usecase *uc_info,
583 st_event_type_t event)
584{
585 bool raise_event = false;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530586 struct audio_event_info ev_info;
587 audio_event_type_t ev;
588 /*Initialize to invalid device*/
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800589 list_init(&ev_info.device_info.devices);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700590
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530591 if (!st_dev)
592 return;
593
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700594 if (uc_info == NULL) {
595 ALOGE("%s: usecase is NULL!!!", __func__);
596 return;
597 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700598
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530599 if ((uc_info->in_snd_device >= SND_DEVICE_IN_BEGIN &&
600 uc_info->in_snd_device < SND_DEVICE_IN_END)) {
601 if (is_same_as_st_device(uc_info->in_snd_device))
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800602 update_device_list(&ev_info.device_info.devices, ST_DEVICE_HANDSET_MIC, "", true);
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530603 } else {
604 ALOGE("%s: invalid input device 0x%x, for event %d",
605 __func__, uc_info->in_snd_device, event);
606 }
607 raise_event = platform_sound_trigger_usecase_needs_event(uc_info->id);
608 ALOGD("%s: uc_info->id %d of type %d for Event %d, with Raise=%d",
609 __func__, uc_info->id, uc_info->type, event, raise_event);
610 if (raise_event) {
611 if (uc_info->type == PCM_PLAYBACK) {
Zhou Songc1088ea2018-06-12 00:17:29 +0800612 if (uc_info->stream.out)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800613 assign_devices(&ev_info.device_info.devices, &uc_info->stream.out->device_list);
Zhou Songc1088ea2018-06-12 00:17:29 +0800614 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800615 reassign_device_list(&ev_info.device_info.devices,
616 AUDIO_DEVICE_OUT_SPEAKER, "");
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530617 switch(event) {
618 case ST_EVENT_STREAM_FREE:
Zhou Songc1088ea2018-06-12 00:17:29 +0800619 st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE, &ev_info);
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530620 break;
621 case ST_EVENT_STREAM_BUSY:
Zhou Songc1088ea2018-06-12 00:17:29 +0800622 st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE, &ev_info);
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530623 break;
624 default:
625 ALOGW("%s:invalid event %d, for usecase %d",
626 __func__, event, uc_info->id);
627 }
Revathi Uddaraju9f99ddd2018-05-03 12:01:38 +0530628 } else if ((uc_info->type == PCM_CAPTURE) || (uc_info->type == VOICE_CALL)) {
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530629 if (event == ST_EVENT_STREAM_BUSY)
630 ev = AUDIO_EVENT_CAPTURE_STREAM_ACTIVE;
631 else
632 ev = AUDIO_EVENT_CAPTURE_STREAM_INACTIVE;
633 if (!populate_usecase(&ev_info.u.usecase, uc_info)) {
634 ALOGD("%s: send event %d: usecase id %d, type %d",
635 __func__, ev, uc_info->id, uc_info->type);
636 st_dev->st_callback(ev, &ev_info);
637 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700638 }
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530639 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700640}
641
Zhou Songc1088ea2018-06-12 00:17:29 +0800642void audio_extn_sound_trigger_update_battery_status(bool charging)
643{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800644 struct audio_event_info ev_info = {{0}, {0}};
Zhou Songc1088ea2018-06-12 00:17:29 +0800645
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800646 if (!st_dev)
Zhou Songc1088ea2018-06-12 00:17:29 +0800647 return;
648
649 ev_info.u.value = charging;
650 st_dev->st_callback(AUDIO_EVENT_BATTERY_STATUS_CHANGED, &ev_info);
651}
652
Quinn Male70f20f32019-06-26 16:50:26 -0700653void audio_extn_sound_trigger_update_screen_status(bool screen_off)
654{
655 struct audio_event_info ev_info = {{0}, {0}};
656
657 if (!st_dev)
658 return;
659
660 ev_info.u.value = screen_off;
661 st_dev->st_callback(AUDIO_EVENT_SCREEN_STATUS_CHANGED, &ev_info);
662}
663
Zhou Songc1088ea2018-06-12 00:17:29 +0800664
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700665void audio_extn_sound_trigger_set_parameters(struct audio_device *adev __unused,
666 struct str_parms *params)
667{
668 audio_event_info_t event;
669 char value[32];
Bharath Ramachandramurthyc694f8a2014-09-25 16:15:12 -0700670 int ret, val;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700671
672 if(!st_dev || !params) {
673 ALOGE("%s: str_params NULL", __func__);
674 return;
675 }
676
Derek Chen6f293672019-04-01 01:40:24 -0700677 stdev_snd_mon_cb(NULL, params);
Bharath Ramachandramurthyc694f8a2014-09-25 16:15:12 -0700678
679 ret = str_parms_get_int(params, "SVA_NUM_SESSIONS", &val);
680 if (ret >= 0) {
681 event.u.value = val;
682 st_dev->st_callback(AUDIO_EVENT_NUM_ST_SESSIONS, &event);
683 }
Quinn male73dd1fd2016-12-02 10:47:11 -0800684
685 ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_CONNECT, &val);
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +0530686 if ((ret >= 0) && (audio_is_input_device(val) ||
687 (val == AUDIO_DEVICE_OUT_LINE))) {
Quinn male73dd1fd2016-12-02 10:47:11 -0800688 event.u.value = val;
689 st_dev->st_callback(AUDIO_EVENT_DEVICE_CONNECT, &event);
690 }
691
692 ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_DISCONNECT, &val);
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +0530693 if ((ret >= 0) && (audio_is_input_device(val) ||
694 (val == AUDIO_DEVICE_OUT_LINE))) {
Quinn male73dd1fd2016-12-02 10:47:11 -0800695 event.u.value = val;
696 st_dev->st_callback(AUDIO_EVENT_DEVICE_DISCONNECT, &event);
697 }
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530698
699 ret = str_parms_get_str(params, "SVA_EXEC_MODE", value, sizeof(value));
700 if (ret >= 0) {
701 strlcpy(event.u.str_value, value, sizeof(event.u.str_value));
702 st_dev->st_callback(AUDIO_EVENT_SVA_EXEC_MODE, &event);
703 }
Aalique Grahame22e49102018-12-18 14:23:57 -0800704
705 ret = str_parms_get_str(params, "SLPI_STATUS", value, sizeof(value));
706 if (ret > 0) {
707 if (strstr(value, "OFFLINE")) {
708 event.u.status = SLPI_STATUS_OFFLINE;
709 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
710 } else if (strstr(value, "ONLINE")) {
711 event.u.status = SLPI_STATUS_ONLINE;
712 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
713 } else
714 ALOGE("%s: unknown SLPI status", __func__);
715 }
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530716}
717
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530718static int extract_sm_handle(const char *keys, char *paramstr) {
719 char *tmpstr, *token;
720 char *inputstr = NULL;
721 int value = -EINVAL;
722
723 if (keys == NULL || paramstr == NULL)
724 goto exit;
725
726 inputstr = strdup(keys);
727 token =strtok_r(inputstr,":", &tmpstr);
728
729 if (token == NULL)
730 goto exit;
731
732 ALOGD("%s input string <%s> param string <%s>", __func__, keys,token);
733 strlcpy(paramstr, token, MAX_STR_LENGTH_FFV_PARAMS);
734 token =strtok_r(NULL,":=",&tmpstr);
735
736 if (token == NULL)
737 goto exit;
738
739 value = atoi(token);
740 if (value > 0 && value < MAX_FFV_SESSION_ID)
741 ALOGD(" %s SVA sm handle<=%d>",__func__, value);
742
743exit:
744 if (inputstr != NULL)
745 free(inputstr);
746
747 return value;
748}
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530749void audio_extn_sound_trigger_get_parameters(const struct audio_device *adev __unused,
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530750 struct str_parms *query,
751 struct str_parms *reply)
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530752{
753 audio_event_info_t event;
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530754 int ret;
755 char value[32], paramstr[MAX_STR_LENGTH_FFV_PARAMS];
Quinn Maled6b0d722020-06-18 13:03:49 -0700756 char *kv_pairs = NULL;
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530757
Quinn Maled6b0d722020-06-18 13:03:49 -0700758 if (query == NULL || reply == NULL) {
Mingshu Pange1a99d92020-06-05 10:38:25 +0800759 ALOGD("%s: query is null or reply is null",__func__);
760 return;
761 }
Quinn Maled6b0d722020-06-18 13:03:49 -0700762
763 kv_pairs = str_parms_to_str(query);
Mingshu Pange1a99d92020-06-05 10:38:25 +0800764 ALOGD("%s input string<%s>", __func__, kv_pairs);
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530765
766 ret = str_parms_get_str(query, "SVA_EXEC_MODE_STATUS", value,
767 sizeof(value));
768 if (ret >= 0) {
769 st_dev->st_callback(AUDIO_EVENT_SVA_EXEC_MODE_STATUS, &event);
770 str_parms_add_int(reply, "SVA_EXEC_MODE_STATUS", event.u.value);
771 }
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530772
Mingshu Pange1a99d92020-06-05 10:38:25 +0800773 ret = extract_sm_handle(kv_pairs, paramstr);
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530774
775 if ((ret >= 0) && !strncmp(paramstr, SVA_PARAM_DIRECTION_OF_ARRIVAL,
776 MAX_STR_LENGTH_FFV_PARAMS)) {
777 event.u.st_get_param_data.sm_handle = ret;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530778 event.u.st_get_param_data.param = SVA_PARAM_DIRECTION_OF_ARRIVAL;
779 event.u.st_get_param_data.reply = reply;
780 st_dev->st_callback(AUDIO_EVENT_GET_PARAM, &event);
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530781 } else if ((ret >=0) && !strncmp(paramstr, SVA_PARAM_CHANNEL_INDEX,
782 MAX_STR_LENGTH_FFV_PARAMS)) {
783 event.u.st_get_param_data.sm_handle = ret;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530784 event.u.st_get_param_data.param = SVA_PARAM_CHANNEL_INDEX;
785 event.u.st_get_param_data.reply = reply;
786 st_dev->st_callback(AUDIO_EVENT_GET_PARAM, &event);
787 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700788}
789
790int audio_extn_sound_trigger_init(struct audio_device *adev)
791{
792 int status = 0;
793 char sound_trigger_lib[100];
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530794 void *sthal_prop_api_version;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700795
796 ALOGI("%s: Enter", __func__);
797
798 st_dev = (struct sound_trigger_audio_device*)
799 calloc(1, sizeof(struct sound_trigger_audio_device));
800 if (!st_dev) {
801 ALOGE("%s: ERROR. sound trigger alloc failed", __func__);
802 return -ENOMEM;
803 }
804
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530805 get_library_path(sound_trigger_lib);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700806 st_dev->lib_handle = dlopen(sound_trigger_lib, RTLD_NOW);
807
808 if (st_dev->lib_handle == NULL) {
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530809 ALOGE("%s: error %s", __func__, dlerror());
810 status = -ENODEV;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700811 goto cleanup;
812 }
813 ALOGI("%s: DLOPEN successful for %s", __func__, sound_trigger_lib);
814
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530815 DLSYM(st_dev->lib_handle, st_dev->st_callback, sound_trigger_hw_call_back,
816 status);
817 if (status)
818 goto cleanup;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700819
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530820 DLSYM(st_dev->lib_handle, sthal_prop_api_version,
821 sthal_prop_api_version, status);
822 if (status) {
823 st_dev->sthal_prop_api_version = 0;
824 status = 0; /* passthru for backward compability */
825 } else {
Jhansi Konathala902fc412018-09-05 13:21:44 +0530826 if (sthal_prop_api_version != NULL) {
827 st_dev->sthal_prop_api_version = *(int*)sthal_prop_api_version;
828 }
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530829 if (MAJOR_VERSION(st_dev->sthal_prop_api_version) !=
830 MAJOR_VERSION(STHAL_PROP_API_CURRENT_VERSION)) {
831 ALOGE("%s: Incompatible API versions ahal:0x%x != sthal:0x%x",
832 __func__, STHAL_PROP_API_CURRENT_VERSION,
833 st_dev->sthal_prop_api_version);
834 goto cleanup;
835 }
836 ALOGD("%s: sthal is using proprietary API version 0x%04x", __func__,
837 st_dev->sthal_prop_api_version);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700838 }
839
840 st_dev->adev = adev;
kunleiz70e57612018-12-28 17:50:23 +0800841 st_dev->st_ec_ref_enabled = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700842 list_init(&st_dev->st_ses_list);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530843 audio_extn_snd_mon_register_listener(st_dev, stdev_snd_mon_cb);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700844
845 return 0;
846
847cleanup:
848 if (st_dev->lib_handle)
849 dlclose(st_dev->lib_handle);
850 free(st_dev);
851 st_dev = NULL;
852 return status;
853
854}
855
856void audio_extn_sound_trigger_deinit(struct audio_device *adev)
857{
858 ALOGI("%s: Enter", __func__);
859 if (st_dev && (st_dev->adev == adev) && st_dev->lib_handle) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530860 audio_extn_snd_mon_unregister_listener(st_dev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700861 dlclose(st_dev->lib_handle);
862 free(st_dev);
863 st_dev = NULL;
864 }
865}