blob: a175b8388694da4ce8573c556e4465d92756aecf [file] [log] [blame]
Aalique Grahame22e49102018-12-18 14:23:57 -08001/* Copyright (c) 2013-2014, 2016-2019 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 */
56#define STHAL_PROP_API_VERSION_1_0 MAKE_HAL_VERSION(1, 0)
kunleiz70e57612018-12-28 17:50:23 +080057#define STHAL_PROP_API_VERSION_1_1 MAKE_HAL_VERSION(1, 1)
58#define STHAL_PROP_API_CURRENT_VERSION STHAL_PROP_API_VERSION_1_1
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +053059
60#define ST_EVENT_CONFIG_MAX_STR_VALUE 32
61#define ST_DEVICE_HANDSET_MIC 1
62
63typedef enum {
64 ST_EVENT_SESSION_REGISTER,
65 ST_EVENT_SESSION_DEREGISTER,
66 ST_EVENT_START_KEEP_ALIVE,
67 ST_EVENT_STOP_KEEP_ALIVE,
kunleiz70e57612018-12-28 17:50:23 +080068 ST_EVENT_UPDATE_ECHO_REF
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +053069} sound_trigger_event_type_t;
70
71typedef enum {
72 AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE,
73 AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE,
74 AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE,
75 AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE,
76 AUDIO_EVENT_STOP_LAB,
77 AUDIO_EVENT_SSR,
78 AUDIO_EVENT_NUM_ST_SESSIONS,
79 AUDIO_EVENT_READ_SAMPLES,
80 AUDIO_EVENT_DEVICE_CONNECT,
81 AUDIO_EVENT_DEVICE_DISCONNECT,
82 AUDIO_EVENT_SVA_EXEC_MODE,
83 AUDIO_EVENT_SVA_EXEC_MODE_STATUS,
84 AUDIO_EVENT_CAPTURE_STREAM_INACTIVE,
85 AUDIO_EVENT_CAPTURE_STREAM_ACTIVE,
Zhou Songc1088ea2018-06-12 00:17:29 +080086 AUDIO_EVENT_BATTERY_STATUS_CHANGED,
kunleiz70e57612018-12-28 17:50:23 +080087 AUDIO_EVENT_GET_PARAM,
Quinn Male918796e2019-07-19 11:19:21 -070088 AUDIO_EVENT_UPDATE_ECHO_REF,
89 AUDIO_EVENT_SCREEN_STATUS_CHANGED
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +053090} audio_event_type_t;
91
92typedef enum {
93 USECASE_TYPE_PCM_PLAYBACK,
94 USECASE_TYPE_PCM_CAPTURE,
95 USECASE_TYPE_VOICE_CALL,
96 USECASE_TYPE_VOIP_CALL,
97} audio_stream_usecase_type_t;
98
99typedef enum {
100 SND_CARD_STATUS_OFFLINE,
101 SND_CARD_STATUS_ONLINE,
102 CPE_STATUS_OFFLINE,
Aalique Grahame22e49102018-12-18 14:23:57 -0800103 CPE_STATUS_ONLINE,
104 SLPI_STATUS_OFFLINE,
105 SLPI_STATUS_ONLINE
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530106} ssr_event_status_t;
107
108struct sound_trigger_session_info {
109 void* p_ses; /* opaque pointer to st_session obj */
110 int capture_handle;
111 struct pcm *pcm;
112 struct pcm_config config;
113};
114
115struct audio_read_samples_info {
116 struct sound_trigger_session_info *ses_info;
117 void *buf;
118 size_t num_bytes;
119};
120
121struct audio_hal_usecase {
122 audio_stream_usecase_type_t type;
123};
124
125struct sound_trigger_event_info {
126 struct sound_trigger_session_info st_ses;
kunleiz70e57612018-12-28 17:50:23 +0800127 bool st_ec_ref_enabled;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530128};
129typedef struct sound_trigger_event_info sound_trigger_event_info_t;
130
131struct sound_trigger_device_info {
132 int device;
133};
134
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530135struct sound_trigger_get_param_data {
136 char *param;
137 int sm_handle;
138 struct str_parms *reply;
139};
140
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530141struct audio_event_info {
142 union {
143 ssr_event_status_t status;
144 int value;
145 struct sound_trigger_session_info ses_info;
146 struct audio_read_samples_info aud_info;
147 char str_value[ST_EVENT_CONFIG_MAX_STR_VALUE];
148 struct audio_hal_usecase usecase;
kunleiz70e57612018-12-28 17:50:23 +0800149 bool audio_ec_ref_enabled;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530150 struct sound_trigger_get_param_data st_get_param_data;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530151 } u;
152 struct sound_trigger_device_info device_info;
153};
154typedef struct audio_event_info audio_event_info_t;
155/* STHAL callback which is called by AHAL */
156typedef int (*sound_trigger_hw_call_back_t)(audio_event_type_t,
157 struct audio_event_info*);
158
159/*---------------- End: AHAL-STHAL Interface ----------------------------------*/
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700160
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +0530161#ifdef DYNAMIC_LOG_ENABLED
162#include <log_xml_parser.h>
163#define LOG_MASK HAL_MOD_FILE_SND_TRIGGER
164#include <log_utils.h>
165#endif
166
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700167#define XSTR(x) STR(x)
168#define STR(x) #x
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530169#define MAX_LIBRARY_PATH 100
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700170
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530171#define DLSYM(handle, ptr, symbol, err) \
172do {\
Venkatesh Mangalappalibcc684c2018-04-06 14:58:44 -0700173 ptr = dlsym(handle, #symbol); \
174 if (ptr == NULL) {\
175 ALOGW("%s: %s not found. %s", __func__, #symbol, dlerror());\
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530176 err = -ENODEV;\
177 }\
178} while(0)
179
180#ifdef __LP64__
181#define SOUND_TRIGGER_LIBRARY_PATH "/vendor/lib64/hw/sound_trigger.primary.%s.so"
182#else
183#define SOUND_TRIGGER_LIBRARY_PATH "/vendor/lib/hw/sound_trigger.primary.%s.so"
184#endif
185
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530186#define SVA_PARAM_DIRECTION_OF_ARRIVAL "st_direction_of_arrival"
187#define SVA_PARAM_CHANNEL_INDEX "st_channel_index"
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530188#define MAX_STR_LENGTH_FFV_PARAMS 30
189#define MAX_FFV_SESSION_ID 100
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530190/*
191 * Current proprietary API version used by AHAL. Queried by STHAL
192 * for compatibility check with AHAL
193 */
194const unsigned int sthal_prop_api_version = STHAL_PROP_API_CURRENT_VERSION;
195
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700196struct sound_trigger_info {
197 struct sound_trigger_session_info st_ses;
198 bool lab_stopped;
199 struct listnode list;
200};
201
202struct sound_trigger_audio_device {
203 void *lib_handle;
204 struct audio_device *adev;
205 sound_trigger_hw_call_back_t st_callback;
206 struct listnode st_ses_list;
207 pthread_mutex_t lock;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530208 unsigned int sthal_prop_api_version;
kunleiz70e57612018-12-28 17:50:23 +0800209 bool st_ec_ref_enabled;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700210};
211
212static struct sound_trigger_audio_device *st_dev;
213
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530214#if LINUX_ENABLED
215static void get_library_path(char *lib_path)
216{
217 snprintf(lib_path, MAX_LIBRARY_PATH,
Manish Dewangan6a36d002017-10-09 14:11:00 +0530218 "sound_trigger.primary.default.so");
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530219}
220#else
221static void get_library_path(char *lib_path)
222{
223 snprintf(lib_path, MAX_LIBRARY_PATH,
David Ng06ccd872017-03-15 11:39:33 -0700224 "/vendor/lib/hw/sound_trigger.primary.%s.so",
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530225 XSTR(SOUND_TRIGGER_PLATFORM_NAME));
226}
227#endif
228
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700229static struct sound_trigger_info *
230get_sound_trigger_info(int capture_handle)
231{
232 struct sound_trigger_info *st_ses_info = NULL;
233 struct listnode *node;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700234 ALOGV("%s: list empty %d capture_handle %d", __func__,
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700235 list_empty(&st_dev->st_ses_list), capture_handle);
236 list_for_each(node, &st_dev->st_ses_list) {
237 st_ses_info = node_to_item(node, struct sound_trigger_info , list);
238 if (st_ses_info->st_ses.capture_handle == capture_handle)
239 return st_ses_info;
240 }
241 return NULL;
242}
243
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530244static int populate_usecase(struct audio_hal_usecase *usecase,
245 struct audio_usecase *uc_info)
246{
247 int status = 0;
248
249 switch(uc_info->type) {
250 case PCM_PLAYBACK:
251 if (uc_info->id == USECASE_AUDIO_PLAYBACK_VOIP)
252 usecase->type = USECASE_TYPE_VOIP_CALL;
253 else
254 usecase->type = USECASE_TYPE_PCM_PLAYBACK;
255 break;
256
257 case PCM_CAPTURE:
258 if (uc_info->id == USECASE_AUDIO_RECORD_VOIP)
259 usecase->type = USECASE_TYPE_VOIP_CALL;
260 else
261 usecase->type = USECASE_TYPE_PCM_CAPTURE;
262 break;
263
264 case VOICE_CALL:
265 usecase->type = USECASE_TYPE_VOICE_CALL;
266 break;
267
268 default:
269 ALOGE("%s: unsupported usecase type %d", __func__, uc_info->type);
270 status = -EINVAL;
271 }
272 return status;
273}
274
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530275static void stdev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
276{
Derek Chen6f293672019-04-01 01:40:24 -0700277 audio_event_info_t event;
278 char value[32];
279 int ret = 0;
280
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530281 if (!parms)
282 return;
283
Derek Chen6f293672019-04-01 01:40:24 -0700284 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value,
285 sizeof(value));
286 if (ret > 0) {
287 if (strstr(value, "OFFLINE")) {
288 event.u.status = SND_CARD_STATUS_OFFLINE;
289 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
290 }
291 else if (strstr(value, "ONLINE")) {
292 event.u.status = SND_CARD_STATUS_ONLINE;
293 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
294 }
295 else
296 ALOGE("%s: unknown snd_card_status", __func__);
297 }
298
299 ret = str_parms_get_str(parms, "CPE_STATUS", value, sizeof(value));
300 if (ret > 0) {
301 if (strstr(value, "OFFLINE")) {
302 event.u.status = CPE_STATUS_OFFLINE;
303 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
304 }
305 else if (strstr(value, "ONLINE")) {
306 event.u.status = CPE_STATUS_ONLINE;
307 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
308 }
309 else
310 ALOGE("%s: unknown CPE status", __func__);
311 }
312
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530313 return;
314}
315
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700316int audio_hw_call_back(sound_trigger_event_type_t event,
317 sound_trigger_event_info_t* config)
318{
319 int status = 0;
320 struct sound_trigger_info *st_ses_info;
321
322 if (!st_dev)
323 return -EINVAL;
324
325 pthread_mutex_lock(&st_dev->lock);
326 switch (event) {
327 case ST_EVENT_SESSION_REGISTER:
328 if (!config) {
329 ALOGE("%s: NULL config", __func__);
330 status = -EINVAL;
331 break;
332 }
333 st_ses_info= calloc(1, sizeof(struct sound_trigger_info ));
334 if (!st_ses_info) {
335 ALOGE("%s: st_ses_info alloc failed", __func__);
336 status = -ENOMEM;
337 break;
338 }
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700339 memcpy(&st_ses_info->st_ses, &config->st_ses, sizeof (struct sound_trigger_session_info));
340 ALOGV("%s: add capture_handle %d st session opaque ptr %p", __func__,
341 st_ses_info->st_ses.capture_handle, st_ses_info->st_ses.p_ses);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700342 list_add_tail(&st_dev->st_ses_list, &st_ses_info->list);
343 break;
344
Surendar Karka59c51072017-12-13 11:25:57 +0530345 case ST_EVENT_START_KEEP_ALIVE:
346 pthread_mutex_unlock(&st_dev->lock);
347 pthread_mutex_lock(&st_dev->adev->lock);
348 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
349 pthread_mutex_unlock(&st_dev->adev->lock);
350 goto done;
351
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700352 case ST_EVENT_SESSION_DEREGISTER:
353 if (!config) {
354 ALOGE("%s: NULL config", __func__);
355 status = -EINVAL;
356 break;
357 }
358 st_ses_info = get_sound_trigger_info(config->st_ses.capture_handle);
359 if (!st_ses_info) {
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700360 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 -0700361 status = -EINVAL;
362 break;
363 }
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700364 ALOGV("%s: remove capture_handle %d st session opaque ptr %p", __func__,
365 st_ses_info->st_ses.capture_handle, st_ses_info->st_ses.p_ses);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700366 list_remove(&st_ses_info->list);
367 free(st_ses_info);
368 break;
Surendar Karka59c51072017-12-13 11:25:57 +0530369
370 case ST_EVENT_STOP_KEEP_ALIVE:
371 pthread_mutex_unlock(&st_dev->lock);
372 pthread_mutex_lock(&st_dev->adev->lock);
373 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
374 pthread_mutex_unlock(&st_dev->adev->lock);
375 goto done;
376
kunleiz70e57612018-12-28 17:50:23 +0800377 case ST_EVENT_UPDATE_ECHO_REF:
378 if (!config) {
379 ALOGE("%s: NULL config", __func__);
380 status = -EINVAL;
381 break;
382 }
383 st_dev->st_ec_ref_enabled = config->st_ec_ref_enabled;
384 break;
385
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700386 default:
387 ALOGW("%s: Unknown event %d", __func__, event);
388 break;
389 }
390 pthread_mutex_unlock(&st_dev->lock);
Surendar Karka59c51072017-12-13 11:25:57 +0530391done:
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700392 return status;
393}
394
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700395int audio_extn_sound_trigger_read(struct stream_in *in, void *buffer,
396 size_t bytes)
397{
398 int ret = -1;
399 struct sound_trigger_info *st_info = NULL;
400 audio_event_info_t event;
401
402 if (!st_dev)
403 return ret;
404
405 if (!in->is_st_session_active) {
406 ALOGE(" %s: Sound trigger is not active", __func__);
407 goto exit;
408 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700409
410 pthread_mutex_lock(&st_dev->lock);
411 st_info = get_sound_trigger_info(in->capture_handle);
412 pthread_mutex_unlock(&st_dev->lock);
413 if (st_info) {
414 event.u.aud_info.ses_info = &st_info->st_ses;
415 event.u.aud_info.buf = buffer;
416 event.u.aud_info.num_bytes = bytes;
417 ret = st_dev->st_callback(AUDIO_EVENT_READ_SAMPLES, &event);
418 }
419
420exit:
421 if (ret) {
422 if (-ENETRESET == ret)
423 in->is_st_session_active = false;
424 memset(buffer, 0, bytes);
425 ALOGV("%s: read failed status %d - sleep", __func__, ret);
426 usleep((bytes * 1000000) / (audio_stream_in_frame_size((struct audio_stream_in *)in) *
427 in->config.rate));
428 }
429 return ret;
430}
431
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700432void audio_extn_sound_trigger_stop_lab(struct stream_in *in)
433{
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700434 struct sound_trigger_info *st_ses_info = NULL;
435 audio_event_info_t event;
436
Mingming Yinfd7607b2016-01-22 12:48:44 -0800437 if (!st_dev || !in || !in->is_st_session_active)
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700438 return;
439
440 pthread_mutex_lock(&st_dev->lock);
441 st_ses_info = get_sound_trigger_info(in->capture_handle);
Bharath Ramachandramurthy5baa6a52014-10-21 11:18:49 -0700442 pthread_mutex_unlock(&st_dev->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700443 if (st_ses_info) {
444 event.u.ses_info = st_ses_info->st_ses;
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700445 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 -0700446 st_dev->st_callback(AUDIO_EVENT_STOP_LAB, &event);
Mingming Yinfd7607b2016-01-22 12:48:44 -0800447 in->is_st_session_active = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700448 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449}
450void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in)
451{
452 struct sound_trigger_info *st_ses_info = NULL;
453 struct listnode *node;
454
455 if (!st_dev || !in)
456 return;
457
458 pthread_mutex_lock(&st_dev->lock);
459 in->is_st_session = false;
460 ALOGV("%s: list %d capture_handle %d", __func__,
461 list_empty(&st_dev->st_ses_list), in->capture_handle);
462 list_for_each(node, &st_dev->st_ses_list) {
463 st_ses_info = node_to_item(node, struct sound_trigger_info , list);
464 if (st_ses_info->st_ses.capture_handle == in->capture_handle) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700465 in->config = st_ses_info->st_ses.config;
466 in->channel_mask = audio_channel_in_mask_from_count(in->config.channels);
467 in->is_st_session = true;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -0800468 in->is_st_session_active = true;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700469 ALOGD("%s: capture_handle %d is sound trigger", __func__, in->capture_handle);
470 break;
471 }
472 }
473 pthread_mutex_unlock(&st_dev->lock);
474}
475
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530476bool is_same_as_st_device(snd_device_t snd_device)
477{
478 if (snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC ||
479 snd_device == SND_DEVICE_IN_HANDSET_MIC ||
480 snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC_NS ||
481 snd_device == SND_DEVICE_IN_SPEAKER_MIC ||
482 snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC ||
483 snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC ||
484 snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC_NS ||
485 snd_device == SND_DEVICE_IN_SPEAKER_MIC_NS) {
486 ALOGD("audio HAL using same device %d as ST", snd_device);
487 return true;
488 }
489 return false;
490}
491
kunleiz70e57612018-12-28 17:50:23 +0800492bool audio_extn_sound_trigger_check_ec_ref_enable()
493{
494 bool ret = false;
495
496 if (!st_dev) {
497 ALOGE("%s: st_dev NULL", __func__);
498 return ret;
499 }
500
501 pthread_mutex_lock(&st_dev->lock);
502 if (st_dev->st_ec_ref_enabled) {
503 ret = true;
504 ALOGD("%s: EC Reference is enabled", __func__);
505 } else {
506 ALOGD("%s: EC Reference is disabled", __func__);
507 }
508 pthread_mutex_unlock(&st_dev->lock);
509
510 return ret;
511}
512
513void audio_extn_sound_trigger_update_ec_ref_status(bool on)
514{
515 struct audio_event_info ev_info;
516
517 if (!st_dev) {
518 ALOGE("%s: st_dev NULL", __func__);
519 return;
520 }
521
522 ev_info.u.audio_ec_ref_enabled = on;
523 st_dev->st_callback(AUDIO_EVENT_UPDATE_ECHO_REF, &ev_info);
524 ALOGD("%s: update audio echo ref status %s",__func__,
525 ev_info.u.audio_ec_ref_enabled == true ? "true" : "false");
526}
527
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700528void audio_extn_sound_trigger_update_device_status(snd_device_t snd_device,
529 st_event_type_t event)
530{
531 bool raise_event = false;
532 int device_type = -1;
533
534 if (!st_dev)
535 return;
536
537 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 &&
541 snd_device < SND_DEVICE_IN_END)
542 device_type = PCM_CAPTURE;
543 else {
544 ALOGE("%s: invalid device 0x%x, for event %d",
545 __func__, snd_device, event);
546 return;
547 }
548
549 raise_event = platform_sound_trigger_device_needs_event(snd_device);
550 ALOGI("%s: device 0x%x of type %d for Event %d, with Raise=%d",
551 __func__, snd_device, device_type, event, raise_event);
552 if (raise_event && (device_type == PCM_CAPTURE)) {
553 switch(event) {
554 case ST_EVENT_SND_DEVICE_FREE:
555 st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, NULL);
556 break;
557 case ST_EVENT_SND_DEVICE_BUSY:
558 st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE, NULL);
559 break;
560 default:
561 ALOGW("%s:invalid event %d for device 0x%x",
562 __func__, event, snd_device);
563 }
564 }/*Events for output device, if required can be placed here in else*/
565}
566
567void audio_extn_sound_trigger_update_stream_status(struct audio_usecase *uc_info,
568 st_event_type_t event)
569{
570 bool raise_event = false;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530571 struct audio_event_info ev_info;
572 audio_event_type_t ev;
573 /*Initialize to invalid device*/
574 ev_info.device_info.device = -1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700575
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530576 if (!st_dev)
577 return;
578
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700579 if (uc_info == NULL) {
580 ALOGE("%s: usecase is NULL!!!", __func__);
581 return;
582 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700583
Dhanalakshmi Siddani24e9ad52018-06-15 14:47:20 +0530584 if ((st_dev->sthal_prop_api_version < STHAL_PROP_API_VERSION_1_0) &&
585 (uc_info->type != PCM_PLAYBACK))
586 return;
587
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530588 if ((uc_info->in_snd_device >= SND_DEVICE_IN_BEGIN &&
589 uc_info->in_snd_device < SND_DEVICE_IN_END)) {
590 if (is_same_as_st_device(uc_info->in_snd_device))
591 ev_info.device_info.device = ST_DEVICE_HANDSET_MIC;
592 } else {
593 ALOGE("%s: invalid input device 0x%x, for event %d",
594 __func__, uc_info->in_snd_device, event);
595 }
596 raise_event = platform_sound_trigger_usecase_needs_event(uc_info->id);
597 ALOGD("%s: uc_info->id %d of type %d for Event %d, with Raise=%d",
598 __func__, uc_info->id, uc_info->type, event, raise_event);
599 if (raise_event) {
600 if (uc_info->type == PCM_PLAYBACK) {
Zhou Songc1088ea2018-06-12 00:17:29 +0800601 if (uc_info->stream.out)
602 ev_info.device_info.device = uc_info->stream.out->devices;
603 else
604 ev_info.device_info.device = AUDIO_DEVICE_OUT_SPEAKER;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530605 switch(event) {
606 case ST_EVENT_STREAM_FREE:
Zhou Songc1088ea2018-06-12 00:17:29 +0800607 st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE, &ev_info);
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530608 break;
609 case ST_EVENT_STREAM_BUSY:
Zhou Songc1088ea2018-06-12 00:17:29 +0800610 st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE, &ev_info);
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530611 break;
612 default:
613 ALOGW("%s:invalid event %d, for usecase %d",
614 __func__, event, uc_info->id);
615 }
Revathi Uddaraju9f99ddd2018-05-03 12:01:38 +0530616 } else if ((uc_info->type == PCM_CAPTURE) || (uc_info->type == VOICE_CALL)) {
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530617 if (event == ST_EVENT_STREAM_BUSY)
618 ev = AUDIO_EVENT_CAPTURE_STREAM_ACTIVE;
619 else
620 ev = AUDIO_EVENT_CAPTURE_STREAM_INACTIVE;
621 if (!populate_usecase(&ev_info.u.usecase, uc_info)) {
622 ALOGD("%s: send event %d: usecase id %d, type %d",
623 __func__, ev, uc_info->id, uc_info->type);
624 st_dev->st_callback(ev, &ev_info);
625 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700626 }
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530627 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700628}
629
Zhou Songc1088ea2018-06-12 00:17:29 +0800630void audio_extn_sound_trigger_update_battery_status(bool charging)
631{
632 struct audio_event_info ev_info;
633
634 if (!st_dev || st_dev->sthal_prop_api_version < STHAL_PROP_API_VERSION_1_0)
635 return;
636
637 ev_info.u.value = charging;
638 st_dev->st_callback(AUDIO_EVENT_BATTERY_STATUS_CHANGED, &ev_info);
639}
640
Quinn Male70f20f32019-06-26 16:50:26 -0700641void audio_extn_sound_trigger_update_screen_status(bool screen_off)
642{
643 struct audio_event_info ev_info = {{0}, {0}};
644
645 if (!st_dev)
646 return;
647
648 ev_info.u.value = screen_off;
649 st_dev->st_callback(AUDIO_EVENT_SCREEN_STATUS_CHANGED, &ev_info);
650}
651
Zhou Songc1088ea2018-06-12 00:17:29 +0800652
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700653void audio_extn_sound_trigger_set_parameters(struct audio_device *adev __unused,
654 struct str_parms *params)
655{
656 audio_event_info_t event;
657 char value[32];
Bharath Ramachandramurthyc694f8a2014-09-25 16:15:12 -0700658 int ret, val;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700659
660 if(!st_dev || !params) {
661 ALOGE("%s: str_params NULL", __func__);
662 return;
663 }
664
Derek Chen6f293672019-04-01 01:40:24 -0700665 stdev_snd_mon_cb(NULL, params);
Bharath Ramachandramurthyc694f8a2014-09-25 16:15:12 -0700666
667 ret = str_parms_get_int(params, "SVA_NUM_SESSIONS", &val);
668 if (ret >= 0) {
669 event.u.value = val;
670 st_dev->st_callback(AUDIO_EVENT_NUM_ST_SESSIONS, &event);
671 }
Quinn male73dd1fd2016-12-02 10:47:11 -0800672
673 ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_CONNECT, &val);
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +0530674 if ((ret >= 0) && (audio_is_input_device(val) ||
675 (val == AUDIO_DEVICE_OUT_LINE))) {
Quinn male73dd1fd2016-12-02 10:47:11 -0800676 event.u.value = val;
677 st_dev->st_callback(AUDIO_EVENT_DEVICE_CONNECT, &event);
678 }
679
680 ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_DISCONNECT, &val);
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +0530681 if ((ret >= 0) && (audio_is_input_device(val) ||
682 (val == AUDIO_DEVICE_OUT_LINE))) {
Quinn male73dd1fd2016-12-02 10:47:11 -0800683 event.u.value = val;
684 st_dev->st_callback(AUDIO_EVENT_DEVICE_DISCONNECT, &event);
685 }
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530686
687 ret = str_parms_get_str(params, "SVA_EXEC_MODE", value, sizeof(value));
688 if (ret >= 0) {
689 strlcpy(event.u.str_value, value, sizeof(event.u.str_value));
690 st_dev->st_callback(AUDIO_EVENT_SVA_EXEC_MODE, &event);
691 }
Aalique Grahame22e49102018-12-18 14:23:57 -0800692
693 ret = str_parms_get_str(params, "SLPI_STATUS", value, sizeof(value));
694 if (ret > 0) {
695 if (strstr(value, "OFFLINE")) {
696 event.u.status = SLPI_STATUS_OFFLINE;
697 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
698 } else if (strstr(value, "ONLINE")) {
699 event.u.status = SLPI_STATUS_ONLINE;
700 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
701 } else
702 ALOGE("%s: unknown SLPI status", __func__);
703 }
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530704}
705
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530706static int extract_sm_handle(const char *keys, char *paramstr) {
707 char *tmpstr, *token;
708 char *inputstr = NULL;
709 int value = -EINVAL;
710
711 if (keys == NULL || paramstr == NULL)
712 goto exit;
713
714 inputstr = strdup(keys);
715 token =strtok_r(inputstr,":", &tmpstr);
716
717 if (token == NULL)
718 goto exit;
719
720 ALOGD("%s input string <%s> param string <%s>", __func__, keys,token);
721 strlcpy(paramstr, token, MAX_STR_LENGTH_FFV_PARAMS);
722 token =strtok_r(NULL,":=",&tmpstr);
723
724 if (token == NULL)
725 goto exit;
726
727 value = atoi(token);
728 if (value > 0 && value < MAX_FFV_SESSION_ID)
729 ALOGD(" %s SVA sm handle<=%d>",__func__, value);
730
731exit:
732 if (inputstr != NULL)
733 free(inputstr);
734
735 return value;
736}
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530737void audio_extn_sound_trigger_get_parameters(const struct audio_device *adev __unused,
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530738 struct str_parms *query,
739 struct str_parms *reply)
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530740{
741 audio_event_info_t event;
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530742 int ret;
743 char value[32], paramstr[MAX_STR_LENGTH_FFV_PARAMS];
744
745 ALOGD("%s input string<%s>", __func__, str_parms_to_str(query));
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530746
747 ret = str_parms_get_str(query, "SVA_EXEC_MODE_STATUS", value,
748 sizeof(value));
749 if (ret >= 0) {
750 st_dev->st_callback(AUDIO_EVENT_SVA_EXEC_MODE_STATUS, &event);
751 str_parms_add_int(reply, "SVA_EXEC_MODE_STATUS", event.u.value);
752 }
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530753
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530754 ret = extract_sm_handle(str_parms_to_str(query), paramstr);
755
756 if ((ret >= 0) && !strncmp(paramstr, SVA_PARAM_DIRECTION_OF_ARRIVAL,
757 MAX_STR_LENGTH_FFV_PARAMS)) {
758 event.u.st_get_param_data.sm_handle = ret;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530759 event.u.st_get_param_data.param = SVA_PARAM_DIRECTION_OF_ARRIVAL;
760 event.u.st_get_param_data.reply = reply;
761 st_dev->st_callback(AUDIO_EVENT_GET_PARAM, &event);
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530762 } else if ((ret >=0) && !strncmp(paramstr, SVA_PARAM_CHANNEL_INDEX,
763 MAX_STR_LENGTH_FFV_PARAMS)) {
764 event.u.st_get_param_data.sm_handle = ret;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530765 event.u.st_get_param_data.param = SVA_PARAM_CHANNEL_INDEX;
766 event.u.st_get_param_data.reply = reply;
767 st_dev->st_callback(AUDIO_EVENT_GET_PARAM, &event);
768 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700769}
770
771int audio_extn_sound_trigger_init(struct audio_device *adev)
772{
773 int status = 0;
774 char sound_trigger_lib[100];
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530775 void *sthal_prop_api_version;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700776
777 ALOGI("%s: Enter", __func__);
778
779 st_dev = (struct sound_trigger_audio_device*)
780 calloc(1, sizeof(struct sound_trigger_audio_device));
781 if (!st_dev) {
782 ALOGE("%s: ERROR. sound trigger alloc failed", __func__);
783 return -ENOMEM;
784 }
785
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530786 get_library_path(sound_trigger_lib);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700787 st_dev->lib_handle = dlopen(sound_trigger_lib, RTLD_NOW);
788
789 if (st_dev->lib_handle == NULL) {
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530790 ALOGE("%s: error %s", __func__, dlerror());
791 status = -ENODEV;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700792 goto cleanup;
793 }
794 ALOGI("%s: DLOPEN successful for %s", __func__, sound_trigger_lib);
795
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530796 DLSYM(st_dev->lib_handle, st_dev->st_callback, sound_trigger_hw_call_back,
797 status);
798 if (status)
799 goto cleanup;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700800
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530801 DLSYM(st_dev->lib_handle, sthal_prop_api_version,
802 sthal_prop_api_version, status);
803 if (status) {
804 st_dev->sthal_prop_api_version = 0;
805 status = 0; /* passthru for backward compability */
806 } else {
Jhansi Konathala902fc412018-09-05 13:21:44 +0530807 if (sthal_prop_api_version != NULL) {
808 st_dev->sthal_prop_api_version = *(int*)sthal_prop_api_version;
809 }
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530810 if (MAJOR_VERSION(st_dev->sthal_prop_api_version) !=
811 MAJOR_VERSION(STHAL_PROP_API_CURRENT_VERSION)) {
812 ALOGE("%s: Incompatible API versions ahal:0x%x != sthal:0x%x",
813 __func__, STHAL_PROP_API_CURRENT_VERSION,
814 st_dev->sthal_prop_api_version);
815 goto cleanup;
816 }
817 ALOGD("%s: sthal is using proprietary API version 0x%04x", __func__,
818 st_dev->sthal_prop_api_version);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700819 }
820
821 st_dev->adev = adev;
kunleiz70e57612018-12-28 17:50:23 +0800822 st_dev->st_ec_ref_enabled = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700823 list_init(&st_dev->st_ses_list);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530824 audio_extn_snd_mon_register_listener(st_dev, stdev_snd_mon_cb);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700825
826 return 0;
827
828cleanup:
829 if (st_dev->lib_handle)
830 dlclose(st_dev->lib_handle);
831 free(st_dev);
832 st_dev = NULL;
833 return status;
834
835}
836
837void audio_extn_sound_trigger_deinit(struct audio_device *adev)
838{
839 ALOGI("%s: Enter", __func__);
840 if (st_dev && (st_dev->adev == adev) && st_dev->lib_handle) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530841 audio_extn_snd_mon_unregister_listener(st_dev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700842 dlclose(st_dev->lib_handle);
843 free(st_dev);
844 st_dev = NULL;
845 }
846}