blob: 4df1ed54886bcbfe0a8396707c8255cb24775b76 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*audio_if.c*/
2#include <fcntl.h>
3#include <unistd.h>
4#include <libubox/blobmsg_json.h>
5#include "libubus.h"
6#include <string.h>
7#include "audio_if.h"
8#include "audio_if_parameter.h"
9#include "audio_if_types.h"
10#include "audio_if_ubus.h"
11#include "audio_if_api.h"
12#include "audio_if_audio_hw_mrvl.h"
13
14#include "utlEventHandler.h"
15#include "udev_monitor.h"
16
17/*************************************************
18* Defines
19**************************************************/
20
21/*************************************************
22* Prototype
23**************************************************/
24extern void AudioIf_uBusFdAdd(int fd);
25extern void AudioIf_uBusUloopRun(void);
26extern int AudioIf_uBusSubscribeEvents(char isSubscribe);
27
28extern void* audio_hal_install(void); //returning ahw_dev handler
29extern void audio_hal_uninstall(void);
30extern int aud_hal_set_hw_device(int audio_device);
31extern void aud_hal_select_output_device(void);
32
33extern int vcm_ctl_read(void *buffer, unsigned int bytes);
34/**************************************************
35* Global variables
36**************************************************/
37AUDIO_IF_DATABASE audioIfDb;
38struct uloop_timeout timeout;
39audioIfReqDb_t audioIfReqDb;
40audioIfUbusDb_t audioIfUbusDb;
41
42audio_hw_device_t *ahw_dev_ubus;
43struct mrvl_audio_device *mrvl_ahw_dev_ubus;
44pthread_mutex_t req_data_mutex;
45pthread_mutex_t AudioIf_mutex;
46pthread_mutex_t AudioIf_Ubus_mutex_play;
47pthread_mutex_t AudioIf_Ubus_mutex_rec;
48
49/* Global variables for headset detection result */
50#if defined(CODEC_PM812)
51//#define HS_STATUS_DEV "/sys/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hs_status"
52//#define HK_STATUS_DEV "/sys/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hk_status"
53#define HS_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hs_status"
54#define HK_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hk_status"
55
56#elif defined(CODEC_ALC5616)
57
58#ifdef TARGET_mmp_asr1901_KSTR901
59#define HS_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616-headset/hs_status"
60#define HK_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616-headset/hk_status"
61#else
62#define HS_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616-headset/hs_status"
63#define HK_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616-headset/hk_status"
64#endif
65
66#else
67//#define HS_STATUS_DEV "/sys/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hs_status"
68//#define HK_STATUS_DEV "/sys/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hk_status"
69#define HS_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hs_status"
70#define HK_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hk_status"
71
72#endif
73
74#define IOCTL_DEV "/dev/audiostub_ctl"
75
76/* Global variables for UTL messages */
77#define AudioIf_UEVENT_BUFFER_SIZE 1024
78static pthread_t AudioIf_utid;
79static int AudioIf_ueventfd = -1;
80static utlEventHandlerId_T AudioIf_ueventHandler;
81static char AudioIf_ueventBuffer[AudioIf_UEVENT_BUFFER_SIZE];
82
83/* Global variables for DTMF Detection */
84#define DTMFCODEID "dtmfcode"
85#define DTMFCODE_NOTIFICATION_NAME "audioif.dtmfcode"
86
87static struct blob_buf DTMFCodeNotify_blob;
88static void AudioIf_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj)
89{
90 UNUSEDPARAM(ctx);
91 UNUSEDPARAM(obj);
92 AUDIO_IF_LOGD("%s, Subscribers active: %s", __FUNCTION__, obj->has_subscribers?"true":"false");
93}
94
95static struct ubus_object_type DTMFCode_object_type;
96static struct ubus_object DTMFCode_notify_obj = {
97 .name = DTMFCODE_NOTIFICATION_NAME,
98 .type = &DTMFCode_object_type,
99 .subscribe_cb = AudioIf_subscribe_cb,
100};
101
102/*----------------voice status----------------*/
103extern unsigned int voice_status;/* bit1:record; bit0:playback; */
104unsigned int old_voice_status = 0;/* bit1:record; bit0:playback; */
105
106/* Global variables for voice status */
107#define VOICESTATUSID "voicestatus"
108#define VOICESTATUS_NOTIFICATION_NAME "audioif.voicestatus"
109
110static struct blob_buf VoiceStatusNotify_blob;
111static void AudioIf_VoiceStatus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj)
112{
113 UNUSEDPARAM(ctx);
114 UNUSEDPARAM(obj);
115 AUDIO_IF_LOGD("%s, Subscribers active: %s", __FUNCTION__, obj->has_subscribers?"true":"false");
116}
117
118static struct ubus_object_type VoiceStatus_object_type;
119static struct ubus_object VoiceStatus_notify_obj = {
120 .name = VOICESTATUS_NOTIFICATION_NAME,
121 .type = &VoiceStatus_object_type,
122 .subscribe_cb = AudioIf_VoiceStatus_subscribe_cb,
123};
124
125/*******************************************************************************\
126* Function: AudioIf_ReadFromDevice
127* Description: This function handle events in ubus context that were sent
128 from audio-HAL through pipe audioIfDb.pipes_fd[1].
129* Returns: void
130\*******************************************************************************/
131void AudioIf_ReadFromDevice(int fd)
132{
133
134// here do:
135// 1. read from audioHAL: (dataLen = read(fd, inbuff, maxControlTransfer)
136// 2. chheck if dataLen!= 0
137// 3. handle the data and process the command
138// see reference code for thi function in MBIM
139 int dataLen, i;
140 char inBuf[AUDIO_IF_AUDIO_STUB_CTRL_BUFF_MAX_LEN];
141
142 memset(inBuf, 0, sizeof(inBuf));
143 //Read from audio_if internal pipe driver
144 if ( (dataLen = read(fd, inBuf, sizeof(inBuf))) < 0 )
145 {
146 AUDIO_IF_LOGE("Error while reading from AUDIO_IF device return\n");
147 return;
148 }
149
150 AUDIO_IF_LOGD("%s: read %d bytes from socket %d", __FUNCTION__, dataLen, fd);
151
152 if (dataLen == 0)
153 {
154 AUDIO_IF_LOGD("Read Zero\n");
155 return;
156 }
157
158 //Dump the data been read
159 for(i = 0; i < dataLen; i++)
160 {
161 AUDIO_IF_LOGD("%s: [%d]=0x%x\n", __FUNCTION__, i, inBuf[i]);
162 }
163}
164
165/*******************************************************************************\
166* Function: AudioIf_BroadcastDTMFCode
167* Description: Broadcast DTMF code using uBus notification
168* Returns: 0: success, -1: fail
169\*******************************************************************************/
170int AudioIf_BroadcastDTMFCode(unsigned short Code)
171{
172 int ret =0;
173
174 blob_buf_init(&DTMFCodeNotify_blob, 0);
175 blobmsg_add_u32(&DTMFCodeNotify_blob, DTMFCODEID, Code);
176
177 ret = ubus_notify(audioIfUbusDb.ctx, &DTMFCode_notify_obj, DTMFCode_notify_obj.name, DTMFCodeNotify_blob.head, -1);
178
179 return ret;
180}
181
182/*******************************************************************************\
183* Function: AudioIf_MainLoopTask
184* Description: This function is a preparation for audio HAL usage in case
185 audio HAL wants to send indications/responses toward audio_if
186 ubus-clients.
187 the function that handle the input from audio HAL in ubus context is
188 AudioIf_ReadFromDevice()
189* Returns: void
190\*******************************************************************************/
191void *AudioIf_MainLoopTask(void *arg)
192{
193 UNUSEDPARAM(arg);
194
195 int dataLen, i;
196 int ret = 0;
197 int sock_fd;
198 char inBuf[AUDIO_IF_AUDIO_STUB_CTRL_BUFF_MAX_LEN];
199
200 struct ATCMsg *p_atc_msg = (struct ATCMsg *)inBuf;
201 unsigned short *p_ecall_msg;
202 char cmd_code, sub_cmd, cmd_type;
203 unsigned short DTMF_code;
204 unsigned short eCall_cmd;
205
206 sock_fd = audioIfDb.pipes_fd[1];
207
208 memset(inBuf, 0, sizeof(inBuf));
209 AUDIO_IF_LOGD("%s: returned socket fd = %d\n", __FUNCTION__, sock_fd);
210 /*This is a thread that listen to audioHAL input into audio_if*/
211 while (TRUE) {
212 AUDIO_IF_LOGD("%s: thread alive\n", __FUNCTION__);
213 //reset received buffer
214 memset(inBuf, 0, sizeof(inBuf));
215
216 if ( (dataLen = vcm_ctl_read(inBuf, sizeof(inBuf))) < 0 ) {
217 AUDIO_IF_LOGE("%s Error while reading from audio control device return\n", __FUNCTION__);
218 sleep(2);
219 continue;
220 }
221
222 if (dataLen == 0) {
223 AUDIO_IF_LOGD("%s Read Zero\n", __FUNCTION__);
224 sleep(2);
225 continue;
226 }
227
228 //Dump the data been read
229 for(i = 0; i < dataLen; i++)
230 {
231 AUDIO_IF_LOGD("%s: [%d]=0x%x\n", __FUNCTION__, i, inBuf[i]);
232 }
233
234 //Get header info
235 cmd_code = p_atc_msg->header.cmd_code; // audio is fixed as 9
236 sub_cmd = p_atc_msg->header.sub_cmd; // 0xa: eCall, 0xc: DTMF detection
237 cmd_type = p_atc_msg->header.cmd_type; // 1: confirm, 2: indication
238
239 //Check whether it is audio cmd
240 if(cmd_code != ATC_AUDIO_CMD) {
241 AUDIO_IF_LOGD("Warning: it is not audio command(%d), cmd_code=%d", ATC_AUDIO_CMD, cmd_code);
242 sleep(2);
243 continue;
244 }
245
246 switch (sub_cmd) {
247 case ATC_ECALLCTL:
248 //Check whether it is eCall indication
249 if(cmd_type != CMD_TYPE_INDICATION) {
250 AUDIO_IF_LOGD("Warning: it is not eCall indication(%d), cmd_type=%d", CMD_TYPE_INDICATION, cmd_type);
251 sleep(2);
252 continue;
253 }
254
255 p_ecall_msg = (unsigned short *) &(p_atc_msg->eCallPayload);
256 eCall_cmd = *(unsigned short *)p_ecall_msg;
257 switch(eCall_cmd){
258 case ACIPC_CODE_AUDIO_VCM_ECALL_DATA_GET_CNF:
259 audio_if_ecall_data_status_response(p_ecall_msg);
260 break;
261
262 case ACIPC_CODE_AUDIO_VCM_ECALL_VOICE_GET_CNF:
263 audio_if_ecall_voice_status_response(p_ecall_msg);
264 break;
265
266 default:
267 AUDIO_IF_LOGD("Unsupport eCall_cmd: 0x%x", eCall_cmd);
268 break;
269 }
270
271 break;
272
273 case ATC_DTMFDETECTIONCTL:
274 DTMF_code = p_atc_msg->DTMF_code;
275 AUDIO_IF_LOGD("Got DTMF code: 0x%x", DTMF_code);
276 ret = AudioIf_BroadcastDTMFCode(DTMF_code);
277 if(ret != 0)
278 AUDIO_IF_LOGD("%s failed to broadcast DTMF code onto uBus, ret=0x%x", __FUNCTION__, ret);
279 break;
280
281 default:
282 AUDIO_IF_LOGD("Unsupport sub_cmd: 0x%x", sub_cmd);
283 break;
284 }
285
286 AUDIO_IF_LOGD("%s: wrote %d bytes to socket %d\n", __FUNCTION__, dataLen, sock_fd);
287 ret = write(sock_fd, inBuf, dataLen);
288 };
289}
290
291int AudioIf_BroadcastVoiceStatus(unsigned int status)
292{
293 int ret =0;
294
295 blob_buf_init(&VoiceStatusNotify_blob, 0);
296 blobmsg_add_u32(&VoiceStatusNotify_blob, VOICESTATUSID, status);
297
298 ret = ubus_notify(audioIfUbusDb.ctx, &VoiceStatus_notify_obj, VoiceStatus_notify_obj.name, VoiceStatusNotify_blob.head, -1);
299
300 return ret;
301}
302
303void AudioIf_report_voice_status(void)
304{
305 if (old_voice_status != voice_status) {
306 AUDIO_IF_LOGD("%s:Got Voice status: %d", __FUNCTION__, voice_status);
307 AudioIf_BroadcastVoiceStatus(voice_status);
308 old_voice_status = voice_status;
309 }
310
311 return;
312}
313/***************************************************************************************\
314* Function: AudioIf_HanldeHeadsetEvent
315* Description: This function handles headset driver reports:
316* /sys/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hs_status
317* /sys/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hk_status
318*
319*
320* Jack types which can be reported.(Defined in Jack.h)
321* enum snd_jack_types {
322* SND_JACK_HEADPHONE = 0x0001,
323* SND_JACK_MICROPHONE = 0x0002,
324* SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
325* SND_JACK_LINEOUT = 0x0004,
326* SND_JACK_MECHANICAL = 0x0008,
327* SND_JACK_VIDEOOUT = 0x0010,
328* SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT,
329* SND_JACK_LINEIN = 0x0020,
330* SND_JACK_BTN_0 = 0x4000,
331* SND_JACK_BTN_1 = 0x2000,
332* SND_JACK_BTN_2 = 0x1000,
333* SND_JACK_BTN_3 = 0x0800,
334* SND_JACK_BTN_4 = 0x0400,
335* SND_JACK_BTN_5 = 0x0200,
336* };
337* Returns: void
338\***************************************************************************************/
339static void AudioIf_HanldeHeadsetEvent(void)
340{
341 int mDev, hk_status, hs_status = 0;
342 char value[32]; //written as '%d'
343
344 /*************************************************************************************
345 * Set correct audio device in boot up phase.
346 * -----------------------------------------------------------------------------------
347 *
348 * In boot up phase, headset driver(88pm800-headset.c) will report headset status, using UEvent.
349 * But, audio_if is started later than headset driver, and miss this UEvent.
350 *
351 * So, audio_if should check the files(HK_STATUS_DEV & HS_STATUS_DEV) created by headset driver
352 * and set the correct audio device.
353 *************************************************************************************/
354
355 /* Open HK_STATUS_DEV */
356 mDev = open(HK_STATUS_DEV, O_RDONLY);
357 if (mDev < 0)
358 {
359 AUDIO_IF_LOGE("%s: Failed to open %s!err=%s\n", __FUNCTION__, HK_STATUS_DEV,strerror(errno));
360 }
361 else
362 {
363 read(mDev, &value, sizeof(value));
364 close(mDev);
365 hk_status = atoi(value);
366 AUDIO_IF_LOGD("%s: Success to open %s, value=%s, hk_status=%d\n", __FUNCTION__, HK_STATUS_DEV, value, hk_status);
367 }
368
369 /* Open HS_STATUS_DEV */
370 mDev = open(HS_STATUS_DEV, O_RDONLY);
371 if (mDev < 0)
372 {
373 AUDIO_IF_LOGE("%s: Failed to open %s!err=%s\n", __FUNCTION__, HS_STATUS_DEV,strerror(errno));
374 }
375 else
376 {
377 read(mDev, &value, sizeof(value));
378 close(mDev);
379 hs_status = atoi(value);
380 AUDIO_IF_LOGD("%s: Success to open %s, value=%s, hs_status=%d\n", __FUNCTION__, HS_STATUS_DEV, value, hs_status);
381 }
382
383 /*************************************************************************************
384 * Set correct audio device according to hs_status
385 * -----------------------------------------------------------------------------------
386 *
387 * hs_status=0, hk_status=0 ==>no headset
388 * hs_status=1, hk_status=0 ==>headphone(without mic)
389 * hs_status=3, hk_status=0 ==>headset(with mic)
390 *************************************************************************************/
391 switch (hs_status)
392 {
393 case 1:
394#ifdef TARGET_mmp_asr1901_KSTR901
395 //For test
396 aud_hal_set_hw_device((int)AUDIO_DEVICE_OUT_WIRED_HEADSET);
397 AUDIO_IF_LOGD("%s: Set audio device = AUDIO_DEVICE_OUT_WIRED_HEADSET \n", __FUNCTION__);
398#else
399 aud_hal_set_hw_device((int)AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
400 AUDIO_IF_LOGD("%s: Set audio device = AUDIO_DEVICE_OUT_WIRED_HEADPHONE \n", __FUNCTION__);
401#endif
402 break;
403
404 case 3:
405 aud_hal_set_hw_device((int)AUDIO_DEVICE_OUT_WIRED_HEADSET);
406 AUDIO_IF_LOGD("%s: Set audio device = AUDIO_DEVICE_OUT_WIRED_HEADSET \n", __FUNCTION__);
407 break;
408
409 case 0:
410 default:
411 /* Align with default audio device in CP audio */
412 aud_hal_set_hw_device((int)AUDIO_DEVICE_OUT_EARPIECE);
413 AUDIO_IF_LOGD("%s: Set audio device = AUDIO_DEVICE_OUT_EARPIECE \n", __FUNCTION__);
414 break;
415 }
416}
417
418
419/***************************************************************************************\
420* Function: AudioIf_HandleDataFromUevent
421* Description: This function handles Uevent
422* For PM812
423* len=430, online@/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset
424* len=424, add@/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset
425* len=430, remove@/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset
426* For ALC5616
427* len=270, add@/devices/soc.0/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616-headset
428* len=276, remove@/devices/soc.0/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616-headset
429* Returns: void
430\***************************************************************************************/
431static int AudioIf_HandleDataFromUevent(char * buf, int buflen)
432{
433 const char * device;
434 const char * action;
435
436 AUDIO_IF_LOGD("%s: len=%d, %s", __FUNCTION__, buflen, buf);
437 device = search_key("DRIVER", buf, buflen);
438 action = search_key("ACTION", buf, buflen);
439
440#if defined(CODEC_PM812)
441 if(device && (!strcmp(device, "88pm800-headset")))
442#elif defined(CODEC_ALC5616)
443 if(device && (!strcmp(device, "alc5616-headset")))
444#else
445 if(0)
446#endif
447 {
448 AUDIO_IF_LOGD("%s: device=%s, action=%s!", __FUNCTION__, device, action);
449
450 if(action && ( (!strcmp(action, "add"))||(!strcmp(action, "remove"))))
451 { //headset plugged or unplugged
452 AudioIf_HanldeHeadsetEvent();
453
454 //Make new audio device take effect, no matter it is in call or not
455 pthread_mutex_lock(&AudioIf_mutex);
456 aud_hal_select_output_device();
457 pthread_mutex_unlock(&AudioIf_mutex);
458 }
459 }
460
461 return 0;
462}
463
464
465static utlReturnCode_T AudioIf_ReceiveDataFromUevent(const utlEventHandlerType_T handler_type,
466 const utlEventHandlerType_T event_type,
467 const int fd,
468 const utlRelativeTime_P2c period_p,
469 void *arg_p)
470{
471 UNUSEDPARAM(handler_type)
472 UNUSEDPARAM(event_type)
473 UNUSEDPARAM(period_p)
474 UNUSEDPARAM(arg_p)
475
476 int ret;
477
478 ret = read(fd, AudioIf_ueventBuffer, AudioIf_UEVENT_BUFFER_SIZE);
479 if(ret > 0)
480 AudioIf_HandleDataFromUevent(AudioIf_ueventBuffer, ret);
481
482 return utlSUCCESS;
483}
484
485
486static int AudioIf_OpenEventLink(void)
487{
488 while(AudioIf_ueventfd < 0)
489 {
490 AudioIf_ueventfd = open_uevent_socket();
491 if(AudioIf_ueventfd < 0)
492 AUDIO_IF_LOGD("open EventLink error:%s\n", strerror(errno));
493 }
494
495 AudioIf_ueventHandler = utlSetFdEventHandler(utlEVENT_HANDLER_TYPE_READ, utlEVENT_HANDLER_PRIORITY_MEDIUM, AudioIf_ueventfd, AudioIf_ReceiveDataFromUevent, NULL);
496
497 return AudioIf_ueventfd;
498}
499
500
501static void AudioIf_CloseEventLink(void)
502{
503 utlDeleteEventHandler(AudioIf_ueventHandler);
504 close(AudioIf_ueventfd);
505 AudioIf_ueventfd = -1;
506}
507
508
509/*******************************************************************************\
510* Function: AudioIf_UTLTask
511* Description: This function is the main task for UTL message.
512* It will firstly set correct audio device;
513* AudioIf_ReceiveDataFromUevent() will handle the input from UTL socket.
514* Returns: void
515\*******************************************************************************/
516static void AudioIf_UTLTask(void)
517{
518 AudioIf_HanldeHeadsetEvent();
519
520 AudioIf_OpenEventLink();
521 if (utlEventLoop(true) != utlSUCCESS)
522 {
523 AUDIO_IF_LOGE("Event loop reports failure!!!");
524 AudioIf_CloseEventLink();
525 return;
526 }
527}
528
529
530/*******************************************************************************\
531* Function: main
532\*******************************************************************************/
533int main(int argc, char **argv)
534{
535 UNUSEDPARAM(argc);
536 UNUSEDPARAM(argv);
537
538 int ioctl_fd, err;
539
540 /* Set log tag for logcat */
541 set_service_log_tag("audio_if");
542
543 /* Wait until audiostub ready */
544 while(1)
545 {
546 ioctl_fd = open(IOCTL_DEV, O_RDONLY);
547 if(ioctl_fd < 0)
548 {
549 err = errno;
550 AUDIO_IF_LOGE("Fail to open %s:%s\n", IOCTL_DEV, strerror(err));
551 sleep(1);
552 continue;
553 }
554 else
555 {
556 AUDIO_IF_LOGD("Success to open %s\n", IOCTL_DEV);
557 close(ioctl_fd);
558 break;
559 }
560 }
561
562 /* Create mutex for Ril and headset interrupt handlers */
563 pthread_mutex_init(&AudioIf_mutex, NULL);
564 pthread_mutex_init(&AudioIf_Ubus_mutex_play, NULL);
565 pthread_mutex_init(&AudioIf_Ubus_mutex_rec, NULL);
566
567 /* Init ubus server */
568 if (AudioIf_uBusInit() != 0) {
569 AUDIO_IF_LOGE("%s: Init ubus server failed!", __FUNCTION__);
570 exit (-1);
571 }
572
573 /* Init global variables */
574 ahw_dev_ubus = audio_hal_install();
575 if (ahw_dev_ubus == NULL) {
576 AUDIO_IF_LOGE("%s: audio_hal_install failed!", __FUNCTION__);
577 exit (-1);
578 }
579
580 mrvl_ahw_dev_ubus = (struct mrvl_audio_device*)ahw_dev_ubus;
581
582 /* Init ubus subscriber */
583 AudioIf_uBusSubscribeEvents(TRUE);
584
585 /* Create a pipe to communicate between (1)ubus thread and (2)audio HAL listner thread */
586 if (pipe(audioIfDb.pipes_fd) != 0) {
587 AUDIO_IF_LOGE("%s: pipe failed with error %d [ %s ].", __FUNCTION__, errno, strerror(errno));
588 exit (-1);
589 }
590 /* Create thread to listen on Audio HAL */
591 pthread_create(&audioIfDb.tid, NULL, AudioIf_MainLoopTask, NULL);
592 /*add fd to the ubus contex. this fd is listen on audioHAL */
593 AudioIf_uBusFdAdd(audioIfDb.pipes_fd[0]);
594
595 /* Add notify object onto bus */
596 ubus_add_object(audioIfUbusDb.ctx, &DTMFCode_notify_obj);
597 ubus_add_object(audioIfUbusDb.ctx, &VoiceStatus_notify_obj);
598
599 /* Create thread to listen to UTL socket */
600 pthread_create(&AudioIf_utid, NULL, (void *)AudioIf_UTLTask, NULL);
601
602 /* Start uloop */
603 AudioIf_uBusUloopRun();
604
605 /* Destroy mutex */
606 pthread_mutex_destroy(&AudioIf_mutex);
607 pthread_mutex_destroy(&AudioIf_Ubus_mutex_play);
608 pthread_mutex_destroy(&AudioIf_Ubus_mutex_rec);
609
610 /* Unregister uloop */
611 /* Thread will get here only if uloop stopped */
612 ubus_remove_object(audioIfUbusDb.ctx, &audioIfUbusDb.server_obj);
613 ubus_free(audioIfUbusDb.ctx);
614 uloop_done();
615
616 /* Unregister subscriber */
617 AudioIf_uBusSubscribeEvents(FALSE);
618
619 /* Unregister server */
620 pthread_cancel(audioIfDb.tid);
621
622 audio_hal_uninstall();
623 exit(0);
624}