blob: aa1f7c00aa9077f17b04b69c7b028a31df2135ab [file] [log] [blame]
Surendar Karka59c51072017-12-13 11:25:57 +05301/* Copyright (c) 2013-2014, 2016-2018 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>
37#include <cutils/log.h>
Vinay Vermaaddfa4a2018-04-29 14:03:38 +053038#include <unistd.h>
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070039#include "audio_hw.h"
40#include "audio_extn.h"
41#include "platform.h"
42#include "platform_api.h"
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +053043
44/*-------------------- Begin: AHAL-STHAL Interface ---------------------------*/
45/*
46 * Maintain the proprietary interface between AHAL and STHAL locally to avoid
47 * the compilation dependency of interface header file from STHAL.
48 */
49
50#define MAKE_HAL_VERSION(maj, min) ((((maj) & 0xff) << 8) | ((min) & 0xff))
51#define MAJOR_VERSION(ver) (((ver) & 0xff00) >> 8)
52#define MINOR_VERSION(ver) ((ver) & 0x00ff)
53
54/* Proprietary interface version used for compatibility with STHAL */
55#define STHAL_PROP_API_VERSION_1_0 MAKE_HAL_VERSION(1, 0)
56#define STHAL_PROP_API_CURRENT_VERSION STHAL_PROP_API_VERSION_1_0
57
58#define ST_EVENT_CONFIG_MAX_STR_VALUE 32
59#define ST_DEVICE_HANDSET_MIC 1
60
61typedef enum {
62 ST_EVENT_SESSION_REGISTER,
63 ST_EVENT_SESSION_DEREGISTER,
64 ST_EVENT_START_KEEP_ALIVE,
65 ST_EVENT_STOP_KEEP_ALIVE,
66} sound_trigger_event_type_t;
67
68typedef enum {
69 AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE,
70 AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE,
71 AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE,
72 AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE,
73 AUDIO_EVENT_STOP_LAB,
74 AUDIO_EVENT_SSR,
75 AUDIO_EVENT_NUM_ST_SESSIONS,
76 AUDIO_EVENT_READ_SAMPLES,
77 AUDIO_EVENT_DEVICE_CONNECT,
78 AUDIO_EVENT_DEVICE_DISCONNECT,
79 AUDIO_EVENT_SVA_EXEC_MODE,
80 AUDIO_EVENT_SVA_EXEC_MODE_STATUS,
81 AUDIO_EVENT_CAPTURE_STREAM_INACTIVE,
82 AUDIO_EVENT_CAPTURE_STREAM_ACTIVE,
Zhou Songc1088ea2018-06-12 00:17:29 +080083 AUDIO_EVENT_BATTERY_STATUS_CHANGED,
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +053084 AUDIO_EVENT_GET_PARAM
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +053085} audio_event_type_t;
86
87typedef enum {
88 USECASE_TYPE_PCM_PLAYBACK,
89 USECASE_TYPE_PCM_CAPTURE,
90 USECASE_TYPE_VOICE_CALL,
91 USECASE_TYPE_VOIP_CALL,
92} audio_stream_usecase_type_t;
93
94typedef enum {
95 SND_CARD_STATUS_OFFLINE,
96 SND_CARD_STATUS_ONLINE,
97 CPE_STATUS_OFFLINE,
98 CPE_STATUS_ONLINE
99} ssr_event_status_t;
100
101struct sound_trigger_session_info {
102 void* p_ses; /* opaque pointer to st_session obj */
103 int capture_handle;
104 struct pcm *pcm;
105 struct pcm_config config;
106};
107
108struct audio_read_samples_info {
109 struct sound_trigger_session_info *ses_info;
110 void *buf;
111 size_t num_bytes;
112};
113
114struct audio_hal_usecase {
115 audio_stream_usecase_type_t type;
116};
117
118struct sound_trigger_event_info {
119 struct sound_trigger_session_info st_ses;
120};
121typedef struct sound_trigger_event_info sound_trigger_event_info_t;
122
123struct sound_trigger_device_info {
124 int device;
125};
126
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530127struct sound_trigger_get_param_data {
128 char *param;
129 int sm_handle;
130 struct str_parms *reply;
131};
132
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530133struct audio_event_info {
134 union {
135 ssr_event_status_t status;
136 int value;
137 struct sound_trigger_session_info ses_info;
138 struct audio_read_samples_info aud_info;
139 char str_value[ST_EVENT_CONFIG_MAX_STR_VALUE];
140 struct audio_hal_usecase usecase;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530141 struct sound_trigger_get_param_data st_get_param_data;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530142 } u;
143 struct sound_trigger_device_info device_info;
144};
145typedef struct audio_event_info audio_event_info_t;
146/* STHAL callback which is called by AHAL */
147typedef int (*sound_trigger_hw_call_back_t)(audio_event_type_t,
148 struct audio_event_info*);
149
150/*---------------- End: AHAL-STHAL Interface ----------------------------------*/
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700151
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +0530152#ifdef DYNAMIC_LOG_ENABLED
153#include <log_xml_parser.h>
154#define LOG_MASK HAL_MOD_FILE_SND_TRIGGER
155#include <log_utils.h>
156#endif
157
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700158#define XSTR(x) STR(x)
159#define STR(x) #x
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530160#define MAX_LIBRARY_PATH 100
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700161
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530162#define DLSYM(handle, ptr, symbol, err) \
163do {\
Venkatesh Mangalappalibcc684c2018-04-06 14:58:44 -0700164 ptr = dlsym(handle, #symbol); \
165 if (ptr == NULL) {\
166 ALOGW("%s: %s not found. %s", __func__, #symbol, dlerror());\
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530167 err = -ENODEV;\
168 }\
169} while(0)
170
171#ifdef __LP64__
172#define SOUND_TRIGGER_LIBRARY_PATH "/vendor/lib64/hw/sound_trigger.primary.%s.so"
173#else
174#define SOUND_TRIGGER_LIBRARY_PATH "/vendor/lib/hw/sound_trigger.primary.%s.so"
175#endif
176
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530177#define SVA_PARAM_DIRECTION_OF_ARRIVAL "st_direction_of_arrival"
178#define SVA_PARAM_CHANNEL_INDEX "st_channel_index"
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530179#define MAX_STR_LENGTH_FFV_PARAMS 30
180#define MAX_FFV_SESSION_ID 100
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530181/*
182 * Current proprietary API version used by AHAL. Queried by STHAL
183 * for compatibility check with AHAL
184 */
185const unsigned int sthal_prop_api_version = STHAL_PROP_API_CURRENT_VERSION;
186
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700187struct sound_trigger_info {
188 struct sound_trigger_session_info st_ses;
189 bool lab_stopped;
190 struct listnode list;
191};
192
193struct sound_trigger_audio_device {
194 void *lib_handle;
195 struct audio_device *adev;
196 sound_trigger_hw_call_back_t st_callback;
197 struct listnode st_ses_list;
198 pthread_mutex_t lock;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530199 unsigned int sthal_prop_api_version;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700200};
201
202static struct sound_trigger_audio_device *st_dev;
203
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530204#if LINUX_ENABLED
205static void get_library_path(char *lib_path)
206{
207 snprintf(lib_path, MAX_LIBRARY_PATH,
Manish Dewangan6a36d002017-10-09 14:11:00 +0530208 "sound_trigger.primary.default.so");
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530209}
210#else
211static void get_library_path(char *lib_path)
212{
213 snprintf(lib_path, MAX_LIBRARY_PATH,
David Ng06ccd872017-03-15 11:39:33 -0700214 "/vendor/lib/hw/sound_trigger.primary.%s.so",
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530215 XSTR(SOUND_TRIGGER_PLATFORM_NAME));
216}
217#endif
218
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700219static struct sound_trigger_info *
220get_sound_trigger_info(int capture_handle)
221{
222 struct sound_trigger_info *st_ses_info = NULL;
223 struct listnode *node;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700224 ALOGV("%s: list empty %d capture_handle %d", __func__,
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700225 list_empty(&st_dev->st_ses_list), capture_handle);
226 list_for_each(node, &st_dev->st_ses_list) {
227 st_ses_info = node_to_item(node, struct sound_trigger_info , list);
228 if (st_ses_info->st_ses.capture_handle == capture_handle)
229 return st_ses_info;
230 }
231 return NULL;
232}
233
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530234static int populate_usecase(struct audio_hal_usecase *usecase,
235 struct audio_usecase *uc_info)
236{
237 int status = 0;
238
239 switch(uc_info->type) {
240 case PCM_PLAYBACK:
241 if (uc_info->id == USECASE_AUDIO_PLAYBACK_VOIP)
242 usecase->type = USECASE_TYPE_VOIP_CALL;
243 else
244 usecase->type = USECASE_TYPE_PCM_PLAYBACK;
245 break;
246
247 case PCM_CAPTURE:
248 if (uc_info->id == USECASE_AUDIO_RECORD_VOIP)
249 usecase->type = USECASE_TYPE_VOIP_CALL;
250 else
251 usecase->type = USECASE_TYPE_PCM_CAPTURE;
252 break;
253
254 case VOICE_CALL:
255 usecase->type = USECASE_TYPE_VOICE_CALL;
256 break;
257
258 default:
259 ALOGE("%s: unsupported usecase type %d", __func__, uc_info->type);
260 status = -EINVAL;
261 }
262 return status;
263}
264
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530265static void stdev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
266{
267 if (!parms)
268 return;
269
270 audio_extn_sound_trigger_set_parameters(NULL, parms);
271 return;
272}
273
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700274int audio_hw_call_back(sound_trigger_event_type_t event,
275 sound_trigger_event_info_t* config)
276{
277 int status = 0;
278 struct sound_trigger_info *st_ses_info;
279
280 if (!st_dev)
281 return -EINVAL;
282
283 pthread_mutex_lock(&st_dev->lock);
284 switch (event) {
285 case ST_EVENT_SESSION_REGISTER:
286 if (!config) {
287 ALOGE("%s: NULL config", __func__);
288 status = -EINVAL;
289 break;
290 }
291 st_ses_info= calloc(1, sizeof(struct sound_trigger_info ));
292 if (!st_ses_info) {
293 ALOGE("%s: st_ses_info alloc failed", __func__);
294 status = -ENOMEM;
295 break;
296 }
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700297 memcpy(&st_ses_info->st_ses, &config->st_ses, sizeof (struct sound_trigger_session_info));
298 ALOGV("%s: add capture_handle %d st session opaque ptr %p", __func__,
299 st_ses_info->st_ses.capture_handle, st_ses_info->st_ses.p_ses);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700300 list_add_tail(&st_dev->st_ses_list, &st_ses_info->list);
301 break;
302
Surendar Karka59c51072017-12-13 11:25:57 +0530303 case ST_EVENT_START_KEEP_ALIVE:
304 pthread_mutex_unlock(&st_dev->lock);
305 pthread_mutex_lock(&st_dev->adev->lock);
306 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
307 pthread_mutex_unlock(&st_dev->adev->lock);
308 goto done;
309
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700310 case ST_EVENT_SESSION_DEREGISTER:
311 if (!config) {
312 ALOGE("%s: NULL config", __func__);
313 status = -EINVAL;
314 break;
315 }
316 st_ses_info = get_sound_trigger_info(config->st_ses.capture_handle);
317 if (!st_ses_info) {
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700318 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 -0700319 status = -EINVAL;
320 break;
321 }
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700322 ALOGV("%s: remove capture_handle %d st session opaque ptr %p", __func__,
323 st_ses_info->st_ses.capture_handle, st_ses_info->st_ses.p_ses);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700324 list_remove(&st_ses_info->list);
325 free(st_ses_info);
326 break;
Surendar Karka59c51072017-12-13 11:25:57 +0530327
328 case ST_EVENT_STOP_KEEP_ALIVE:
329 pthread_mutex_unlock(&st_dev->lock);
330 pthread_mutex_lock(&st_dev->adev->lock);
331 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
332 pthread_mutex_unlock(&st_dev->adev->lock);
333 goto done;
334
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700335 default:
336 ALOGW("%s: Unknown event %d", __func__, event);
337 break;
338 }
339 pthread_mutex_unlock(&st_dev->lock);
Surendar Karka59c51072017-12-13 11:25:57 +0530340done:
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700341 return status;
342}
343
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700344int audio_extn_sound_trigger_read(struct stream_in *in, void *buffer,
345 size_t bytes)
346{
347 int ret = -1;
348 struct sound_trigger_info *st_info = NULL;
349 audio_event_info_t event;
350
351 if (!st_dev)
352 return ret;
353
354 if (!in->is_st_session_active) {
355 ALOGE(" %s: Sound trigger is not active", __func__);
356 goto exit;
357 }
358 if(in->standby)
359 in->standby = false;
360
361 pthread_mutex_lock(&st_dev->lock);
362 st_info = get_sound_trigger_info(in->capture_handle);
363 pthread_mutex_unlock(&st_dev->lock);
364 if (st_info) {
365 event.u.aud_info.ses_info = &st_info->st_ses;
366 event.u.aud_info.buf = buffer;
367 event.u.aud_info.num_bytes = bytes;
368 ret = st_dev->st_callback(AUDIO_EVENT_READ_SAMPLES, &event);
369 }
370
371exit:
372 if (ret) {
373 if (-ENETRESET == ret)
374 in->is_st_session_active = false;
375 memset(buffer, 0, bytes);
376 ALOGV("%s: read failed status %d - sleep", __func__, ret);
377 usleep((bytes * 1000000) / (audio_stream_in_frame_size((struct audio_stream_in *)in) *
378 in->config.rate));
379 }
380 return ret;
381}
382
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700383void audio_extn_sound_trigger_stop_lab(struct stream_in *in)
384{
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700385 struct sound_trigger_info *st_ses_info = NULL;
386 audio_event_info_t event;
387
Mingming Yinfd7607b2016-01-22 12:48:44 -0800388 if (!st_dev || !in || !in->is_st_session_active)
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700389 return;
390
391 pthread_mutex_lock(&st_dev->lock);
392 st_ses_info = get_sound_trigger_info(in->capture_handle);
Bharath Ramachandramurthy5baa6a52014-10-21 11:18:49 -0700393 pthread_mutex_unlock(&st_dev->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700394 if (st_ses_info) {
395 event.u.ses_info = st_ses_info->st_ses;
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700396 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 -0700397 st_dev->st_callback(AUDIO_EVENT_STOP_LAB, &event);
Mingming Yinfd7607b2016-01-22 12:48:44 -0800398 in->is_st_session_active = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700399 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700400}
401void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in)
402{
403 struct sound_trigger_info *st_ses_info = NULL;
404 struct listnode *node;
405
406 if (!st_dev || !in)
407 return;
408
409 pthread_mutex_lock(&st_dev->lock);
410 in->is_st_session = false;
411 ALOGV("%s: list %d capture_handle %d", __func__,
412 list_empty(&st_dev->st_ses_list), in->capture_handle);
413 list_for_each(node, &st_dev->st_ses_list) {
414 st_ses_info = node_to_item(node, struct sound_trigger_info , list);
415 if (st_ses_info->st_ses.capture_handle == in->capture_handle) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700416 in->config = st_ses_info->st_ses.config;
417 in->channel_mask = audio_channel_in_mask_from_count(in->config.channels);
418 in->is_st_session = true;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -0800419 in->is_st_session_active = true;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700420 ALOGD("%s: capture_handle %d is sound trigger", __func__, in->capture_handle);
421 break;
422 }
423 }
424 pthread_mutex_unlock(&st_dev->lock);
425}
426
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530427bool is_same_as_st_device(snd_device_t snd_device)
428{
429 if (snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC ||
430 snd_device == SND_DEVICE_IN_HANDSET_MIC ||
431 snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC_NS ||
432 snd_device == SND_DEVICE_IN_SPEAKER_MIC ||
433 snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC ||
434 snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC ||
435 snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC_NS ||
436 snd_device == SND_DEVICE_IN_SPEAKER_MIC_NS) {
437 ALOGD("audio HAL using same device %d as ST", snd_device);
438 return true;
439 }
440 return false;
441}
442
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700443void audio_extn_sound_trigger_update_device_status(snd_device_t snd_device,
444 st_event_type_t event)
445{
446 bool raise_event = false;
447 int device_type = -1;
448
449 if (!st_dev)
450 return;
451
452 if (snd_device >= SND_DEVICE_OUT_BEGIN &&
453 snd_device < SND_DEVICE_OUT_END)
454 device_type = PCM_PLAYBACK;
455 else if (snd_device >= SND_DEVICE_IN_BEGIN &&
456 snd_device < SND_DEVICE_IN_END)
457 device_type = PCM_CAPTURE;
458 else {
459 ALOGE("%s: invalid device 0x%x, for event %d",
460 __func__, snd_device, event);
461 return;
462 }
463
464 raise_event = platform_sound_trigger_device_needs_event(snd_device);
465 ALOGI("%s: device 0x%x of type %d for Event %d, with Raise=%d",
466 __func__, snd_device, device_type, event, raise_event);
467 if (raise_event && (device_type == PCM_CAPTURE)) {
468 switch(event) {
469 case ST_EVENT_SND_DEVICE_FREE:
470 st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, NULL);
471 break;
472 case ST_EVENT_SND_DEVICE_BUSY:
473 st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE, NULL);
474 break;
475 default:
476 ALOGW("%s:invalid event %d for device 0x%x",
477 __func__, event, snd_device);
478 }
479 }/*Events for output device, if required can be placed here in else*/
480}
481
482void audio_extn_sound_trigger_update_stream_status(struct audio_usecase *uc_info,
483 st_event_type_t event)
484{
485 bool raise_event = false;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530486 struct audio_event_info ev_info;
487 audio_event_type_t ev;
488 /*Initialize to invalid device*/
489 ev_info.device_info.device = -1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700490
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530491 if (!st_dev)
492 return;
493
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700494 if (uc_info == NULL) {
495 ALOGE("%s: usecase is NULL!!!", __func__);
496 return;
497 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700498
Dhanalakshmi Siddani24e9ad52018-06-15 14:47:20 +0530499 if ((st_dev->sthal_prop_api_version < STHAL_PROP_API_VERSION_1_0) &&
500 (uc_info->type != PCM_PLAYBACK))
501 return;
502
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530503 if ((uc_info->in_snd_device >= SND_DEVICE_IN_BEGIN &&
504 uc_info->in_snd_device < SND_DEVICE_IN_END)) {
505 if (is_same_as_st_device(uc_info->in_snd_device))
506 ev_info.device_info.device = ST_DEVICE_HANDSET_MIC;
507 } else {
508 ALOGE("%s: invalid input device 0x%x, for event %d",
509 __func__, uc_info->in_snd_device, event);
510 }
511 raise_event = platform_sound_trigger_usecase_needs_event(uc_info->id);
512 ALOGD("%s: uc_info->id %d of type %d for Event %d, with Raise=%d",
513 __func__, uc_info->id, uc_info->type, event, raise_event);
514 if (raise_event) {
515 if (uc_info->type == PCM_PLAYBACK) {
Zhou Songc1088ea2018-06-12 00:17:29 +0800516 if (uc_info->stream.out)
517 ev_info.device_info.device = uc_info->stream.out->devices;
518 else
519 ev_info.device_info.device = AUDIO_DEVICE_OUT_SPEAKER;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530520 switch(event) {
521 case ST_EVENT_STREAM_FREE:
Zhou Songc1088ea2018-06-12 00:17:29 +0800522 st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE, &ev_info);
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530523 break;
524 case ST_EVENT_STREAM_BUSY:
Zhou Songc1088ea2018-06-12 00:17:29 +0800525 st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE, &ev_info);
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530526 break;
527 default:
528 ALOGW("%s:invalid event %d, for usecase %d",
529 __func__, event, uc_info->id);
530 }
Revathi Uddaraju9f99ddd2018-05-03 12:01:38 +0530531 } else if ((uc_info->type == PCM_CAPTURE) || (uc_info->type == VOICE_CALL)) {
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530532 if (event == ST_EVENT_STREAM_BUSY)
533 ev = AUDIO_EVENT_CAPTURE_STREAM_ACTIVE;
534 else
535 ev = AUDIO_EVENT_CAPTURE_STREAM_INACTIVE;
536 if (!populate_usecase(&ev_info.u.usecase, uc_info)) {
537 ALOGD("%s: send event %d: usecase id %d, type %d",
538 __func__, ev, uc_info->id, uc_info->type);
539 st_dev->st_callback(ev, &ev_info);
540 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700541 }
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530542 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700543}
544
Zhou Songc1088ea2018-06-12 00:17:29 +0800545void audio_extn_sound_trigger_update_battery_status(bool charging)
546{
547 struct audio_event_info ev_info;
548
549 if (!st_dev || st_dev->sthal_prop_api_version < STHAL_PROP_API_VERSION_1_0)
550 return;
551
552 ev_info.u.value = charging;
553 st_dev->st_callback(AUDIO_EVENT_BATTERY_STATUS_CHANGED, &ev_info);
554}
555
556
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700557void audio_extn_sound_trigger_set_parameters(struct audio_device *adev __unused,
558 struct str_parms *params)
559{
560 audio_event_info_t event;
561 char value[32];
Bharath Ramachandramurthyc694f8a2014-09-25 16:15:12 -0700562 int ret, val;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700563
564 if(!st_dev || !params) {
565 ALOGE("%s: str_params NULL", __func__);
566 return;
567 }
568
569 ret = str_parms_get_str(params, "SND_CARD_STATUS", value,
570 sizeof(value));
571 if (ret > 0) {
572 if (strstr(value, "OFFLINE")) {
573 event.u.status = SND_CARD_STATUS_OFFLINE;
574 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
575 }
576 else if (strstr(value, "ONLINE")) {
577 event.u.status = SND_CARD_STATUS_ONLINE;
578 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
579 }
580 else
581 ALOGE("%s: unknown snd_card_status", __func__);
582 }
583
584 ret = str_parms_get_str(params, "CPE_STATUS", value, sizeof(value));
585 if (ret > 0) {
586 if (strstr(value, "OFFLINE")) {
587 event.u.status = CPE_STATUS_OFFLINE;
588 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
589 }
590 else if (strstr(value, "ONLINE")) {
591 event.u.status = CPE_STATUS_ONLINE;
592 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
593 }
594 else
595 ALOGE("%s: unknown CPE status", __func__);
596 }
Bharath Ramachandramurthyc694f8a2014-09-25 16:15:12 -0700597
598 ret = str_parms_get_int(params, "SVA_NUM_SESSIONS", &val);
599 if (ret >= 0) {
600 event.u.value = val;
601 st_dev->st_callback(AUDIO_EVENT_NUM_ST_SESSIONS, &event);
602 }
Quinn male73dd1fd2016-12-02 10:47:11 -0800603
604 ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_CONNECT, &val);
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +0530605 if ((ret >= 0) && (audio_is_input_device(val) ||
606 (val == AUDIO_DEVICE_OUT_LINE))) {
Quinn male73dd1fd2016-12-02 10:47:11 -0800607 event.u.value = val;
608 st_dev->st_callback(AUDIO_EVENT_DEVICE_CONNECT, &event);
609 }
610
611 ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_DISCONNECT, &val);
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +0530612 if ((ret >= 0) && (audio_is_input_device(val) ||
613 (val == AUDIO_DEVICE_OUT_LINE))) {
Quinn male73dd1fd2016-12-02 10:47:11 -0800614 event.u.value = val;
615 st_dev->st_callback(AUDIO_EVENT_DEVICE_DISCONNECT, &event);
616 }
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530617
618 ret = str_parms_get_str(params, "SVA_EXEC_MODE", value, sizeof(value));
619 if (ret >= 0) {
620 strlcpy(event.u.str_value, value, sizeof(event.u.str_value));
621 st_dev->st_callback(AUDIO_EVENT_SVA_EXEC_MODE, &event);
622 }
623}
624
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530625static int extract_sm_handle(const char *keys, char *paramstr) {
626 char *tmpstr, *token;
627 char *inputstr = NULL;
628 int value = -EINVAL;
629
630 if (keys == NULL || paramstr == NULL)
631 goto exit;
632
633 inputstr = strdup(keys);
634 token =strtok_r(inputstr,":", &tmpstr);
635
636 if (token == NULL)
637 goto exit;
638
639 ALOGD("%s input string <%s> param string <%s>", __func__, keys,token);
640 strlcpy(paramstr, token, MAX_STR_LENGTH_FFV_PARAMS);
641 token =strtok_r(NULL,":=",&tmpstr);
642
643 if (token == NULL)
644 goto exit;
645
646 value = atoi(token);
647 if (value > 0 && value < MAX_FFV_SESSION_ID)
648 ALOGD(" %s SVA sm handle<=%d>",__func__, value);
649
650exit:
651 if (inputstr != NULL)
652 free(inputstr);
653
654 return value;
655}
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530656void audio_extn_sound_trigger_get_parameters(const struct audio_device *adev __unused,
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530657 struct str_parms *query,
658 struct str_parms *reply)
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530659{
660 audio_event_info_t event;
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530661 int ret;
662 char value[32], paramstr[MAX_STR_LENGTH_FFV_PARAMS];
663
664 ALOGD("%s input string<%s>", __func__, str_parms_to_str(query));
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530665
666 ret = str_parms_get_str(query, "SVA_EXEC_MODE_STATUS", value,
667 sizeof(value));
668 if (ret >= 0) {
669 st_dev->st_callback(AUDIO_EVENT_SVA_EXEC_MODE_STATUS, &event);
670 str_parms_add_int(reply, "SVA_EXEC_MODE_STATUS", event.u.value);
671 }
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530672
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530673 ret = extract_sm_handle(str_parms_to_str(query), paramstr);
674
675 if ((ret >= 0) && !strncmp(paramstr, SVA_PARAM_DIRECTION_OF_ARRIVAL,
676 MAX_STR_LENGTH_FFV_PARAMS)) {
677 event.u.st_get_param_data.sm_handle = ret;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530678 event.u.st_get_param_data.param = SVA_PARAM_DIRECTION_OF_ARRIVAL;
679 event.u.st_get_param_data.reply = reply;
680 st_dev->st_callback(AUDIO_EVENT_GET_PARAM, &event);
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +0530681 } else if ((ret >=0) && !strncmp(paramstr, SVA_PARAM_CHANNEL_INDEX,
682 MAX_STR_LENGTH_FFV_PARAMS)) {
683 event.u.st_get_param_data.sm_handle = ret;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530684 event.u.st_get_param_data.param = SVA_PARAM_CHANNEL_INDEX;
685 event.u.st_get_param_data.reply = reply;
686 st_dev->st_callback(AUDIO_EVENT_GET_PARAM, &event);
687 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700688}
689
690int audio_extn_sound_trigger_init(struct audio_device *adev)
691{
692 int status = 0;
693 char sound_trigger_lib[100];
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530694 void *sthal_prop_api_version;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700695
696 ALOGI("%s: Enter", __func__);
697
698 st_dev = (struct sound_trigger_audio_device*)
699 calloc(1, sizeof(struct sound_trigger_audio_device));
700 if (!st_dev) {
701 ALOGE("%s: ERROR. sound trigger alloc failed", __func__);
702 return -ENOMEM;
703 }
704
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530705 get_library_path(sound_trigger_lib);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700706 st_dev->lib_handle = dlopen(sound_trigger_lib, RTLD_NOW);
707
708 if (st_dev->lib_handle == NULL) {
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530709 ALOGE("%s: error %s", __func__, dlerror());
710 status = -ENODEV;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700711 goto cleanup;
712 }
713 ALOGI("%s: DLOPEN successful for %s", __func__, sound_trigger_lib);
714
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530715 DLSYM(st_dev->lib_handle, st_dev->st_callback, sound_trigger_hw_call_back,
716 status);
717 if (status)
718 goto cleanup;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700719
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530720 DLSYM(st_dev->lib_handle, sthal_prop_api_version,
721 sthal_prop_api_version, status);
722 if (status) {
723 st_dev->sthal_prop_api_version = 0;
724 status = 0; /* passthru for backward compability */
725 } else {
Jhansi Konathala902fc412018-09-05 13:21:44 +0530726 if (sthal_prop_api_version != NULL) {
727 st_dev->sthal_prop_api_version = *(int*)sthal_prop_api_version;
728 }
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530729 if (MAJOR_VERSION(st_dev->sthal_prop_api_version) !=
730 MAJOR_VERSION(STHAL_PROP_API_CURRENT_VERSION)) {
731 ALOGE("%s: Incompatible API versions ahal:0x%x != sthal:0x%x",
732 __func__, STHAL_PROP_API_CURRENT_VERSION,
733 st_dev->sthal_prop_api_version);
734 goto cleanup;
735 }
736 ALOGD("%s: sthal is using proprietary API version 0x%04x", __func__,
737 st_dev->sthal_prop_api_version);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700738 }
739
740 st_dev->adev = adev;
741 list_init(&st_dev->st_ses_list);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530742 audio_extn_snd_mon_register_listener(st_dev, stdev_snd_mon_cb);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700743
744 return 0;
745
746cleanup:
747 if (st_dev->lib_handle)
748 dlclose(st_dev->lib_handle);
749 free(st_dev);
750 st_dev = NULL;
751 return status;
752
753}
754
755void audio_extn_sound_trigger_deinit(struct audio_device *adev)
756{
757 ALOGI("%s: Enter", __func__);
758 if (st_dev && (st_dev->adev == adev) && st_dev->lib_handle) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530759 audio_extn_snd_mon_unregister_listener(st_dev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700760 dlclose(st_dev->lib_handle);
761 free(st_dev);
762 st_dev = NULL;
763 }
764}