blob: 909ef8fc79e47cfd0023cd746002495dd2e0d424 [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>
38#include "audio_hw.h"
39#include "audio_extn.h"
40#include "platform.h"
41#include "platform_api.h"
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +053042
43/*-------------------- Begin: AHAL-STHAL Interface ---------------------------*/
44/*
45 * Maintain the proprietary interface between AHAL and STHAL locally to avoid
46 * the compilation dependency of interface header file from STHAL.
47 */
48
49#define MAKE_HAL_VERSION(maj, min) ((((maj) & 0xff) << 8) | ((min) & 0xff))
50#define MAJOR_VERSION(ver) (((ver) & 0xff00) >> 8)
51#define MINOR_VERSION(ver) ((ver) & 0x00ff)
52
53/* Proprietary interface version used for compatibility with STHAL */
54#define STHAL_PROP_API_VERSION_1_0 MAKE_HAL_VERSION(1, 0)
55#define STHAL_PROP_API_CURRENT_VERSION STHAL_PROP_API_VERSION_1_0
56
57#define ST_EVENT_CONFIG_MAX_STR_VALUE 32
58#define ST_DEVICE_HANDSET_MIC 1
59
60typedef enum {
61 ST_EVENT_SESSION_REGISTER,
62 ST_EVENT_SESSION_DEREGISTER,
63 ST_EVENT_START_KEEP_ALIVE,
64 ST_EVENT_STOP_KEEP_ALIVE,
65} sound_trigger_event_type_t;
66
67typedef enum {
68 AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE,
69 AUDIO_EVENT_CAPTURE_DEVICE_ACTIVE,
70 AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE,
71 AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE,
72 AUDIO_EVENT_STOP_LAB,
73 AUDIO_EVENT_SSR,
74 AUDIO_EVENT_NUM_ST_SESSIONS,
75 AUDIO_EVENT_READ_SAMPLES,
76 AUDIO_EVENT_DEVICE_CONNECT,
77 AUDIO_EVENT_DEVICE_DISCONNECT,
78 AUDIO_EVENT_SVA_EXEC_MODE,
79 AUDIO_EVENT_SVA_EXEC_MODE_STATUS,
80 AUDIO_EVENT_CAPTURE_STREAM_INACTIVE,
81 AUDIO_EVENT_CAPTURE_STREAM_ACTIVE,
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +053082 AUDIO_EVENT_GET_PARAM
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +053083} audio_event_type_t;
84
85typedef enum {
86 USECASE_TYPE_PCM_PLAYBACK,
87 USECASE_TYPE_PCM_CAPTURE,
88 USECASE_TYPE_VOICE_CALL,
89 USECASE_TYPE_VOIP_CALL,
90} audio_stream_usecase_type_t;
91
92typedef enum {
93 SND_CARD_STATUS_OFFLINE,
94 SND_CARD_STATUS_ONLINE,
95 CPE_STATUS_OFFLINE,
96 CPE_STATUS_ONLINE
97} ssr_event_status_t;
98
99struct sound_trigger_session_info {
100 void* p_ses; /* opaque pointer to st_session obj */
101 int capture_handle;
102 struct pcm *pcm;
103 struct pcm_config config;
104};
105
106struct audio_read_samples_info {
107 struct sound_trigger_session_info *ses_info;
108 void *buf;
109 size_t num_bytes;
110};
111
112struct audio_hal_usecase {
113 audio_stream_usecase_type_t type;
114};
115
116struct sound_trigger_event_info {
117 struct sound_trigger_session_info st_ses;
118};
119typedef struct sound_trigger_event_info sound_trigger_event_info_t;
120
121struct sound_trigger_device_info {
122 int device;
123};
124
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530125struct sound_trigger_get_param_data {
126 char *param;
127 int sm_handle;
128 struct str_parms *reply;
129};
130
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530131struct audio_event_info {
132 union {
133 ssr_event_status_t status;
134 int value;
135 struct sound_trigger_session_info ses_info;
136 struct audio_read_samples_info aud_info;
137 char str_value[ST_EVENT_CONFIG_MAX_STR_VALUE];
138 struct audio_hal_usecase usecase;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530139 struct sound_trigger_get_param_data st_get_param_data;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530140 } u;
141 struct sound_trigger_device_info device_info;
142};
143typedef struct audio_event_info audio_event_info_t;
144/* STHAL callback which is called by AHAL */
145typedef int (*sound_trigger_hw_call_back_t)(audio_event_type_t,
146 struct audio_event_info*);
147
148/*---------------- End: AHAL-STHAL Interface ----------------------------------*/
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700149
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +0530150#ifdef DYNAMIC_LOG_ENABLED
151#include <log_xml_parser.h>
152#define LOG_MASK HAL_MOD_FILE_SND_TRIGGER
153#include <log_utils.h>
154#endif
155
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700156#define XSTR(x) STR(x)
157#define STR(x) #x
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530158#define MAX_LIBRARY_PATH 100
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700159
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530160#define DLSYM(handle, ptr, symbol, err) \
161do {\
162 const char* error; \
163 *(void**)&ptr = dlsym(handle, #symbol); \
164 if ((error = dlerror())) {\
165 ALOGE("%s: ERROR. %s", __func__, error);\
166 err = -ENODEV;\
167 }\
168} while(0)
169
170#ifdef __LP64__
171#define SOUND_TRIGGER_LIBRARY_PATH "/vendor/lib64/hw/sound_trigger.primary.%s.so"
172#else
173#define SOUND_TRIGGER_LIBRARY_PATH "/vendor/lib/hw/sound_trigger.primary.%s.so"
174#endif
175
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530176#define SVA_PARAM_DIRECTION_OF_ARRIVAL "st_direction_of_arrival"
177#define SVA_PARAM_CHANNEL_INDEX "st_channel_index"
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530178/*
179 * Current proprietary API version used by AHAL. Queried by STHAL
180 * for compatibility check with AHAL
181 */
182const unsigned int sthal_prop_api_version = STHAL_PROP_API_CURRENT_VERSION;
183
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700184struct sound_trigger_info {
185 struct sound_trigger_session_info st_ses;
186 bool lab_stopped;
187 struct listnode list;
188};
189
190struct sound_trigger_audio_device {
191 void *lib_handle;
192 struct audio_device *adev;
193 sound_trigger_hw_call_back_t st_callback;
194 struct listnode st_ses_list;
195 pthread_mutex_t lock;
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530196 unsigned int sthal_prop_api_version;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700197};
198
199static struct sound_trigger_audio_device *st_dev;
200
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530201#if LINUX_ENABLED
202static void get_library_path(char *lib_path)
203{
204 snprintf(lib_path, MAX_LIBRARY_PATH,
Manish Dewangan6a36d002017-10-09 14:11:00 +0530205 "sound_trigger.primary.default.so");
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530206}
207#else
208static void get_library_path(char *lib_path)
209{
210 snprintf(lib_path, MAX_LIBRARY_PATH,
David Ng06ccd872017-03-15 11:39:33 -0700211 "/vendor/lib/hw/sound_trigger.primary.%s.so",
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530212 XSTR(SOUND_TRIGGER_PLATFORM_NAME));
213}
214#endif
215
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700216static struct sound_trigger_info *
217get_sound_trigger_info(int capture_handle)
218{
219 struct sound_trigger_info *st_ses_info = NULL;
220 struct listnode *node;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700221 ALOGV("%s: list empty %d capture_handle %d", __func__,
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700222 list_empty(&st_dev->st_ses_list), capture_handle);
223 list_for_each(node, &st_dev->st_ses_list) {
224 st_ses_info = node_to_item(node, struct sound_trigger_info , list);
225 if (st_ses_info->st_ses.capture_handle == capture_handle)
226 return st_ses_info;
227 }
228 return NULL;
229}
230
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530231static int populate_usecase(struct audio_hal_usecase *usecase,
232 struct audio_usecase *uc_info)
233{
234 int status = 0;
235
236 switch(uc_info->type) {
237 case PCM_PLAYBACK:
238 if (uc_info->id == USECASE_AUDIO_PLAYBACK_VOIP)
239 usecase->type = USECASE_TYPE_VOIP_CALL;
240 else
241 usecase->type = USECASE_TYPE_PCM_PLAYBACK;
242 break;
243
244 case PCM_CAPTURE:
245 if (uc_info->id == USECASE_AUDIO_RECORD_VOIP)
246 usecase->type = USECASE_TYPE_VOIP_CALL;
247 else
248 usecase->type = USECASE_TYPE_PCM_CAPTURE;
249 break;
250
251 case VOICE_CALL:
252 usecase->type = USECASE_TYPE_VOICE_CALL;
253 break;
254
255 default:
256 ALOGE("%s: unsupported usecase type %d", __func__, uc_info->type);
257 status = -EINVAL;
258 }
259 return status;
260}
261
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530262static void stdev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
263{
264 if (!parms)
265 return;
266
267 audio_extn_sound_trigger_set_parameters(NULL, parms);
268 return;
269}
270
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700271int audio_hw_call_back(sound_trigger_event_type_t event,
272 sound_trigger_event_info_t* config)
273{
274 int status = 0;
275 struct sound_trigger_info *st_ses_info;
276
277 if (!st_dev)
278 return -EINVAL;
279
280 pthread_mutex_lock(&st_dev->lock);
281 switch (event) {
282 case ST_EVENT_SESSION_REGISTER:
283 if (!config) {
284 ALOGE("%s: NULL config", __func__);
285 status = -EINVAL;
286 break;
287 }
288 st_ses_info= calloc(1, sizeof(struct sound_trigger_info ));
289 if (!st_ses_info) {
290 ALOGE("%s: st_ses_info alloc failed", __func__);
291 status = -ENOMEM;
292 break;
293 }
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700294 memcpy(&st_ses_info->st_ses, &config->st_ses, sizeof (struct sound_trigger_session_info));
295 ALOGV("%s: add capture_handle %d st session opaque ptr %p", __func__,
296 st_ses_info->st_ses.capture_handle, st_ses_info->st_ses.p_ses);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700297 list_add_tail(&st_dev->st_ses_list, &st_ses_info->list);
298 break;
299
Surendar Karka59c51072017-12-13 11:25:57 +0530300 case ST_EVENT_START_KEEP_ALIVE:
301 pthread_mutex_unlock(&st_dev->lock);
302 pthread_mutex_lock(&st_dev->adev->lock);
303 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
304 pthread_mutex_unlock(&st_dev->adev->lock);
305 goto done;
306
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700307 case ST_EVENT_SESSION_DEREGISTER:
308 if (!config) {
309 ALOGE("%s: NULL config", __func__);
310 status = -EINVAL;
311 break;
312 }
313 st_ses_info = get_sound_trigger_info(config->st_ses.capture_handle);
314 if (!st_ses_info) {
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700315 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 -0700316 status = -EINVAL;
317 break;
318 }
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700319 ALOGV("%s: remove capture_handle %d st session opaque ptr %p", __func__,
320 st_ses_info->st_ses.capture_handle, st_ses_info->st_ses.p_ses);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700321 list_remove(&st_ses_info->list);
322 free(st_ses_info);
323 break;
Surendar Karka59c51072017-12-13 11:25:57 +0530324
325 case ST_EVENT_STOP_KEEP_ALIVE:
326 pthread_mutex_unlock(&st_dev->lock);
327 pthread_mutex_lock(&st_dev->adev->lock);
328 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
329 pthread_mutex_unlock(&st_dev->adev->lock);
330 goto done;
331
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700332 default:
333 ALOGW("%s: Unknown event %d", __func__, event);
334 break;
335 }
336 pthread_mutex_unlock(&st_dev->lock);
Surendar Karka59c51072017-12-13 11:25:57 +0530337done:
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700338 return status;
339}
340
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -0700341int audio_extn_sound_trigger_read(struct stream_in *in, void *buffer,
342 size_t bytes)
343{
344 int ret = -1;
345 struct sound_trigger_info *st_info = NULL;
346 audio_event_info_t event;
347
348 if (!st_dev)
349 return ret;
350
351 if (!in->is_st_session_active) {
352 ALOGE(" %s: Sound trigger is not active", __func__);
353 goto exit;
354 }
355 if(in->standby)
356 in->standby = false;
357
358 pthread_mutex_lock(&st_dev->lock);
359 st_info = get_sound_trigger_info(in->capture_handle);
360 pthread_mutex_unlock(&st_dev->lock);
361 if (st_info) {
362 event.u.aud_info.ses_info = &st_info->st_ses;
363 event.u.aud_info.buf = buffer;
364 event.u.aud_info.num_bytes = bytes;
365 ret = st_dev->st_callback(AUDIO_EVENT_READ_SAMPLES, &event);
366 }
367
368exit:
369 if (ret) {
370 if (-ENETRESET == ret)
371 in->is_st_session_active = false;
372 memset(buffer, 0, bytes);
373 ALOGV("%s: read failed status %d - sleep", __func__, ret);
374 usleep((bytes * 1000000) / (audio_stream_in_frame_size((struct audio_stream_in *)in) *
375 in->config.rate));
376 }
377 return ret;
378}
379
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700380void audio_extn_sound_trigger_stop_lab(struct stream_in *in)
381{
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700382 struct sound_trigger_info *st_ses_info = NULL;
383 audio_event_info_t event;
384
Mingming Yinfd7607b2016-01-22 12:48:44 -0800385 if (!st_dev || !in || !in->is_st_session_active)
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700386 return;
387
388 pthread_mutex_lock(&st_dev->lock);
389 st_ses_info = get_sound_trigger_info(in->capture_handle);
Bharath Ramachandramurthy5baa6a52014-10-21 11:18:49 -0700390 pthread_mutex_unlock(&st_dev->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700391 if (st_ses_info) {
392 event.u.ses_info = st_ses_info->st_ses;
Shiv Maliyappanahalli0e283d32016-07-14 23:20:03 -0700393 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 -0700394 st_dev->st_callback(AUDIO_EVENT_STOP_LAB, &event);
Mingming Yinfd7607b2016-01-22 12:48:44 -0800395 in->is_st_session_active = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700396 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700397}
398void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in)
399{
400 struct sound_trigger_info *st_ses_info = NULL;
401 struct listnode *node;
402
403 if (!st_dev || !in)
404 return;
405
406 pthread_mutex_lock(&st_dev->lock);
407 in->is_st_session = false;
408 ALOGV("%s: list %d capture_handle %d", __func__,
409 list_empty(&st_dev->st_ses_list), in->capture_handle);
410 list_for_each(node, &st_dev->st_ses_list) {
411 st_ses_info = node_to_item(node, struct sound_trigger_info , list);
412 if (st_ses_info->st_ses.capture_handle == in->capture_handle) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700413 in->config = st_ses_info->st_ses.config;
414 in->channel_mask = audio_channel_in_mask_from_count(in->config.channels);
415 in->is_st_session = true;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -0800416 in->is_st_session_active = true;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700417 ALOGD("%s: capture_handle %d is sound trigger", __func__, in->capture_handle);
418 break;
419 }
420 }
421 pthread_mutex_unlock(&st_dev->lock);
422}
423
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530424bool is_same_as_st_device(snd_device_t snd_device)
425{
426 if (snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC ||
427 snd_device == SND_DEVICE_IN_HANDSET_MIC ||
428 snd_device == SND_DEVICE_IN_HANDSET_MIC_AEC_NS ||
429 snd_device == SND_DEVICE_IN_SPEAKER_MIC ||
430 snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC ||
431 snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC ||
432 snd_device == SND_DEVICE_IN_SPEAKER_MIC_AEC_NS ||
433 snd_device == SND_DEVICE_IN_SPEAKER_MIC_NS) {
434 ALOGD("audio HAL using same device %d as ST", snd_device);
435 return true;
436 }
437 return false;
438}
439
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700440void audio_extn_sound_trigger_update_device_status(snd_device_t snd_device,
441 st_event_type_t event)
442{
443 bool raise_event = false;
444 int device_type = -1;
445
446 if (!st_dev)
447 return;
448
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530449 if (st_dev->sthal_prop_api_version >= STHAL_PROP_API_VERSION_1_0)
450 return;
451
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700452 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
494 if (st_dev->sthal_prop_api_version < STHAL_PROP_API_VERSION_1_0)
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700495 return;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700496
497 if (uc_info == NULL) {
498 ALOGE("%s: usecase is NULL!!!", __func__);
499 return;
500 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700501
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530502 if ((uc_info->in_snd_device >= SND_DEVICE_IN_BEGIN &&
503 uc_info->in_snd_device < SND_DEVICE_IN_END)) {
504 if (is_same_as_st_device(uc_info->in_snd_device))
505 ev_info.device_info.device = ST_DEVICE_HANDSET_MIC;
506 } else {
507 ALOGE("%s: invalid input device 0x%x, for event %d",
508 __func__, uc_info->in_snd_device, event);
509 }
510 raise_event = platform_sound_trigger_usecase_needs_event(uc_info->id);
511 ALOGD("%s: uc_info->id %d of type %d for Event %d, with Raise=%d",
512 __func__, uc_info->id, uc_info->type, event, raise_event);
513 if (raise_event) {
514 if (uc_info->type == PCM_PLAYBACK) {
515 switch(event) {
516 case ST_EVENT_STREAM_FREE:
517 st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_INACTIVE, NULL);
518 break;
519 case ST_EVENT_STREAM_BUSY:
520 st_dev->st_callback(AUDIO_EVENT_PLAYBACK_STREAM_ACTIVE, NULL);
521 break;
522 default:
523 ALOGW("%s:invalid event %d, for usecase %d",
524 __func__, event, uc_info->id);
525 }
Revathi Uddarajub46af6c2018-05-03 12:01:38 +0530526 } else if ((uc_info->type == PCM_CAPTURE) || (uc_info->type == VOICE_CALL)) {
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530527 if (event == ST_EVENT_STREAM_BUSY)
528 ev = AUDIO_EVENT_CAPTURE_STREAM_ACTIVE;
529 else
530 ev = AUDIO_EVENT_CAPTURE_STREAM_INACTIVE;
531 if (!populate_usecase(&ev_info.u.usecase, uc_info)) {
532 ALOGD("%s: send event %d: usecase id %d, type %d",
533 __func__, ev, uc_info->id, uc_info->type);
534 st_dev->st_callback(ev, &ev_info);
535 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 }
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530537 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700538}
539
540void audio_extn_sound_trigger_set_parameters(struct audio_device *adev __unused,
541 struct str_parms *params)
542{
543 audio_event_info_t event;
544 char value[32];
Bharath Ramachandramurthyc694f8a2014-09-25 16:15:12 -0700545 int ret, val;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700546
547 if(!st_dev || !params) {
548 ALOGE("%s: str_params NULL", __func__);
549 return;
550 }
551
552 ret = str_parms_get_str(params, "SND_CARD_STATUS", value,
553 sizeof(value));
554 if (ret > 0) {
555 if (strstr(value, "OFFLINE")) {
556 event.u.status = SND_CARD_STATUS_OFFLINE;
557 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
558 }
559 else if (strstr(value, "ONLINE")) {
560 event.u.status = SND_CARD_STATUS_ONLINE;
561 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
562 }
563 else
564 ALOGE("%s: unknown snd_card_status", __func__);
565 }
566
567 ret = str_parms_get_str(params, "CPE_STATUS", value, sizeof(value));
568 if (ret > 0) {
569 if (strstr(value, "OFFLINE")) {
570 event.u.status = CPE_STATUS_OFFLINE;
571 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
572 }
573 else if (strstr(value, "ONLINE")) {
574 event.u.status = CPE_STATUS_ONLINE;
575 st_dev->st_callback(AUDIO_EVENT_SSR, &event);
576 }
577 else
578 ALOGE("%s: unknown CPE status", __func__);
579 }
Bharath Ramachandramurthyc694f8a2014-09-25 16:15:12 -0700580
581 ret = str_parms_get_int(params, "SVA_NUM_SESSIONS", &val);
582 if (ret >= 0) {
583 event.u.value = val;
584 st_dev->st_callback(AUDIO_EVENT_NUM_ST_SESSIONS, &event);
585 }
Quinn male73dd1fd2016-12-02 10:47:11 -0800586
587 ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_CONNECT, &val);
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +0530588 if ((ret >= 0) && (audio_is_input_device(val) ||
589 (val == AUDIO_DEVICE_OUT_LINE))) {
Quinn male73dd1fd2016-12-02 10:47:11 -0800590 event.u.value = val;
591 st_dev->st_callback(AUDIO_EVENT_DEVICE_CONNECT, &event);
592 }
593
594 ret = str_parms_get_int(params, AUDIO_PARAMETER_DEVICE_DISCONNECT, &val);
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +0530595 if ((ret >= 0) && (audio_is_input_device(val) ||
596 (val == AUDIO_DEVICE_OUT_LINE))) {
Quinn male73dd1fd2016-12-02 10:47:11 -0800597 event.u.value = val;
598 st_dev->st_callback(AUDIO_EVENT_DEVICE_DISCONNECT, &event);
599 }
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530600
601 ret = str_parms_get_str(params, "SVA_EXEC_MODE", value, sizeof(value));
602 if (ret >= 0) {
603 strlcpy(event.u.str_value, value, sizeof(event.u.str_value));
604 st_dev->st_callback(AUDIO_EVENT_SVA_EXEC_MODE, &event);
605 }
606}
607
608void audio_extn_sound_trigger_get_parameters(const struct audio_device *adev __unused,
609 struct str_parms *query, struct str_parms *reply)
610{
611 audio_event_info_t event;
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530612 int ret, val;
Chaithanya Krishna Bacharajue3d711e2016-12-08 16:17:32 +0530613 char value[32];
614
615 ret = str_parms_get_str(query, "SVA_EXEC_MODE_STATUS", value,
616 sizeof(value));
617 if (ret >= 0) {
618 st_dev->st_callback(AUDIO_EVENT_SVA_EXEC_MODE_STATUS, &event);
619 str_parms_add_int(reply, "SVA_EXEC_MODE_STATUS", event.u.value);
620 }
Dhanalakshmi Siddani57b014e2018-04-23 12:52:02 +0530621
622 ret = str_parms_get_int(query, SVA_PARAM_DIRECTION_OF_ARRIVAL, &val);
623 if (ret >= 0) {
624 event.u.st_get_param_data.sm_handle = val;
625 event.u.st_get_param_data.param = SVA_PARAM_DIRECTION_OF_ARRIVAL;
626 event.u.st_get_param_data.reply = reply;
627 st_dev->st_callback(AUDIO_EVENT_GET_PARAM, &event);
628 }
629
630 ret = str_parms_get_int(query, SVA_PARAM_CHANNEL_INDEX, &val);
631 if (ret >= 0) {
632 event.u.st_get_param_data.sm_handle = val;
633 event.u.st_get_param_data.param = SVA_PARAM_CHANNEL_INDEX;
634 event.u.st_get_param_data.reply = reply;
635 st_dev->st_callback(AUDIO_EVENT_GET_PARAM, &event);
636 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700637}
638
639int audio_extn_sound_trigger_init(struct audio_device *adev)
640{
641 int status = 0;
642 char sound_trigger_lib[100];
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530643 void *sthal_prop_api_version;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700644
645 ALOGI("%s: Enter", __func__);
646
647 st_dev = (struct sound_trigger_audio_device*)
648 calloc(1, sizeof(struct sound_trigger_audio_device));
649 if (!st_dev) {
650 ALOGE("%s: ERROR. sound trigger alloc failed", __func__);
651 return -ENOMEM;
652 }
653
Yamit Mehtaa0d653a2016-11-25 20:33:25 +0530654 get_library_path(sound_trigger_lib);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700655 st_dev->lib_handle = dlopen(sound_trigger_lib, RTLD_NOW);
656
657 if (st_dev->lib_handle == NULL) {
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530658 ALOGE("%s: error %s", __func__, dlerror());
659 status = -ENODEV;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700660 goto cleanup;
661 }
662 ALOGI("%s: DLOPEN successful for %s", __func__, sound_trigger_lib);
663
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530664 dlerror();
665 DLSYM(st_dev->lib_handle, st_dev->st_callback, sound_trigger_hw_call_back,
666 status);
667 if (status)
668 goto cleanup;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700669
Dhanalakshmi Siddanif133cc52018-02-08 14:34:51 +0530670 DLSYM(st_dev->lib_handle, sthal_prop_api_version,
671 sthal_prop_api_version, status);
672 if (status) {
673 st_dev->sthal_prop_api_version = 0;
674 status = 0; /* passthru for backward compability */
675 } else {
676 st_dev->sthal_prop_api_version = *(int*)sthal_prop_api_version;
677 if (MAJOR_VERSION(st_dev->sthal_prop_api_version) !=
678 MAJOR_VERSION(STHAL_PROP_API_CURRENT_VERSION)) {
679 ALOGE("%s: Incompatible API versions ahal:0x%x != sthal:0x%x",
680 __func__, STHAL_PROP_API_CURRENT_VERSION,
681 st_dev->sthal_prop_api_version);
682 goto cleanup;
683 }
684 ALOGD("%s: sthal is using proprietary API version 0x%04x", __func__,
685 st_dev->sthal_prop_api_version);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700686 }
687
688 st_dev->adev = adev;
689 list_init(&st_dev->st_ses_list);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530690 audio_extn_snd_mon_register_listener(st_dev, stdev_snd_mon_cb);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700691
692 return 0;
693
694cleanup:
695 if (st_dev->lib_handle)
696 dlclose(st_dev->lib_handle);
697 free(st_dev);
698 st_dev = NULL;
699 return status;
700
701}
702
703void audio_extn_sound_trigger_deinit(struct audio_device *adev)
704{
705 ALOGI("%s: Enter", __func__);
706 if (st_dev && (st_dev->adev == adev) && st_dev->lib_handle) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530707 audio_extn_snd_mon_unregister_listener(st_dev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700708 dlclose(st_dev->lib_handle);
709 free(st_dev);
710 st_dev = NULL;
711 }
712}