| /*audio_if.c*/ |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <libubox/blobmsg_json.h> |
| #include "libubus.h" |
| #include <string.h> |
| #include "audio_if.h" |
| #include "audio_if_parameter.h" |
| #include "audio_if_types.h" |
| #include "audio_if_ubus.h" |
| #include "audio_if_api.h" |
| #include "audio_if_audio_hw_mrvl.h" |
| |
| #include "utlEventHandler.h" |
| #include "udev_monitor.h" |
| |
| /************************************************* |
| * Defines |
| **************************************************/ |
| |
| /************************************************* |
| * Prototype |
| **************************************************/ |
| extern void AudioIf_uBusFdAdd(int fd); |
| extern void AudioIf_uBusUloopRun(void); |
| extern int AudioIf_uBusSubscribeEvents(char isSubscribe); |
| |
| extern void* audio_hal_install(void); //returning ahw_dev handler |
| extern void audio_hal_uninstall(void); |
| extern int aud_hal_set_hw_device(int audio_device); |
| extern void aud_hal_select_output_device(void); |
| |
| extern int vcm_ctl_read(void *buffer, unsigned int bytes); |
| /************************************************** |
| * Global variables |
| **************************************************/ |
| AUDIO_IF_DATABASE audioIfDb; |
| struct uloop_timeout timeout; |
| audioIfReqDb_t audioIfReqDb; |
| audioIfUbusDb_t audioIfUbusDb; |
| |
| audio_hw_device_t *ahw_dev_ubus; |
| struct mrvl_audio_device *mrvl_ahw_dev_ubus; |
| pthread_mutex_t req_data_mutex; |
| pthread_mutex_t AudioIf_mutex; |
| pthread_mutex_t AudioIf_Ubus_mutex_play; |
| pthread_mutex_t AudioIf_Ubus_mutex_rec; |
| |
| /* Global variables for headset detection result */ |
| #if defined(CODEC_PM812) |
| //#define HS_STATUS_DEV "/sys/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hs_status" |
| //#define HK_STATUS_DEV "/sys/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hk_status" |
| #define HS_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hs_status" |
| #define HK_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hk_status" |
| |
| #elif defined(CODEC_ALC5616) |
| |
| #ifdef TARGET_mmp_asr1901_KSTR901 |
| #define HS_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616-headset/hs_status" |
| #define HK_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-001b/alc5616-headset/hk_status" |
| #else |
| #define HS_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616-headset/hs_status" |
| #define HK_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616-headset/hk_status" |
| #endif |
| |
| #else |
| //#define HS_STATUS_DEV "/sys/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hs_status" |
| //#define HK_STATUS_DEV "/sys/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hk_status" |
| #define HS_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hs_status" |
| #define HK_STATUS_DEV "/sys/devices/platform/soc/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hk_status" |
| |
| #endif |
| |
| #define IOCTL_DEV "/dev/audiostub_ctl" |
| |
| /* Global variables for UTL messages */ |
| #define AudioIf_UEVENT_BUFFER_SIZE 1024 |
| static pthread_t AudioIf_utid; |
| static int AudioIf_ueventfd = -1; |
| static utlEventHandlerId_T AudioIf_ueventHandler; |
| static char AudioIf_ueventBuffer[AudioIf_UEVENT_BUFFER_SIZE]; |
| |
| /* Global variables for DTMF Detection */ |
| #define DTMFCODEID "dtmfcode" |
| #define DTMFCODE_NOTIFICATION_NAME "audioif.dtmfcode" |
| |
| static struct blob_buf DTMFCodeNotify_blob; |
| static void AudioIf_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj) |
| { |
| UNUSEDPARAM(ctx); |
| UNUSEDPARAM(obj); |
| AUDIO_IF_LOGD("%s, Subscribers active: %s", __FUNCTION__, obj->has_subscribers?"true":"false"); |
| } |
| |
| static struct ubus_object_type DTMFCode_object_type; |
| static struct ubus_object DTMFCode_notify_obj = { |
| .name = DTMFCODE_NOTIFICATION_NAME, |
| .type = &DTMFCode_object_type, |
| .subscribe_cb = AudioIf_subscribe_cb, |
| }; |
| |
| /*----------------voice status----------------*/ |
| extern unsigned int voice_status;/* bit1:record; bit0:playback; */ |
| unsigned int old_voice_status = 0;/* bit1:record; bit0:playback; */ |
| |
| /* Global variables for voice status */ |
| #define VOICESTATUSID "voicestatus" |
| #define VOICESTATUS_NOTIFICATION_NAME "audioif.voicestatus" |
| |
| static struct blob_buf VoiceStatusNotify_blob; |
| static void AudioIf_VoiceStatus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj) |
| { |
| UNUSEDPARAM(ctx); |
| UNUSEDPARAM(obj); |
| AUDIO_IF_LOGD("%s, Subscribers active: %s", __FUNCTION__, obj->has_subscribers?"true":"false"); |
| } |
| |
| static struct ubus_object_type VoiceStatus_object_type; |
| static struct ubus_object VoiceStatus_notify_obj = { |
| .name = VOICESTATUS_NOTIFICATION_NAME, |
| .type = &VoiceStatus_object_type, |
| .subscribe_cb = AudioIf_VoiceStatus_subscribe_cb, |
| }; |
| |
| /*******************************************************************************\ |
| * Function: AudioIf_ReadFromDevice |
| * Description: This function handle events in ubus context that were sent |
| from audio-HAL through pipe audioIfDb.pipes_fd[1]. |
| * Returns: void |
| \*******************************************************************************/ |
| void AudioIf_ReadFromDevice(int fd) |
| { |
| |
| // here do: |
| // 1. read from audioHAL: (dataLen = read(fd, inbuff, maxControlTransfer) |
| // 2. chheck if dataLen!= 0 |
| // 3. handle the data and process the command |
| // see reference code for thi function in MBIM |
| int dataLen, i; |
| char inBuf[AUDIO_IF_AUDIO_STUB_CTRL_BUFF_MAX_LEN]; |
| |
| memset(inBuf, 0, sizeof(inBuf)); |
| //Read from audio_if internal pipe driver |
| if ( (dataLen = read(fd, inBuf, sizeof(inBuf))) < 0 ) |
| { |
| AUDIO_IF_LOGE("Error while reading from AUDIO_IF device return\n"); |
| return; |
| } |
| |
| AUDIO_IF_LOGD("%s: read %d bytes from socket %d", __FUNCTION__, dataLen, fd); |
| |
| if (dataLen == 0) |
| { |
| AUDIO_IF_LOGD("Read Zero\n"); |
| return; |
| } |
| |
| //Dump the data been read |
| for(i = 0; i < dataLen; i++) |
| { |
| AUDIO_IF_LOGD("%s: [%d]=0x%x\n", __FUNCTION__, i, inBuf[i]); |
| } |
| } |
| |
| /*******************************************************************************\ |
| * Function: AudioIf_BroadcastDTMFCode |
| * Description: Broadcast DTMF code using uBus notification |
| * Returns: 0: success, -1: fail |
| \*******************************************************************************/ |
| int AudioIf_BroadcastDTMFCode(unsigned short Code) |
| { |
| int ret =0; |
| |
| blob_buf_init(&DTMFCodeNotify_blob, 0); |
| blobmsg_add_u32(&DTMFCodeNotify_blob, DTMFCODEID, Code); |
| |
| ret = ubus_notify(audioIfUbusDb.ctx, &DTMFCode_notify_obj, DTMFCode_notify_obj.name, DTMFCodeNotify_blob.head, -1); |
| |
| return ret; |
| } |
| |
| /*******************************************************************************\ |
| * Function: AudioIf_MainLoopTask |
| * Description: This function is a preparation for audio HAL usage in case |
| audio HAL wants to send indications/responses toward audio_if |
| ubus-clients. |
| the function that handle the input from audio HAL in ubus context is |
| AudioIf_ReadFromDevice() |
| * Returns: void |
| \*******************************************************************************/ |
| void *AudioIf_MainLoopTask(void *arg) |
| { |
| UNUSEDPARAM(arg); |
| |
| int dataLen, i; |
| int ret = 0; |
| int sock_fd; |
| char inBuf[AUDIO_IF_AUDIO_STUB_CTRL_BUFF_MAX_LEN]; |
| |
| struct ATCMsg *p_atc_msg = (struct ATCMsg *)inBuf; |
| unsigned short *p_ecall_msg; |
| char cmd_code, sub_cmd, cmd_type; |
| unsigned short DTMF_code; |
| unsigned short eCall_cmd; |
| |
| sock_fd = audioIfDb.pipes_fd[1]; |
| |
| memset(inBuf, 0, sizeof(inBuf)); |
| AUDIO_IF_LOGD("%s: returned socket fd = %d\n", __FUNCTION__, sock_fd); |
| /*This is a thread that listen to audioHAL input into audio_if*/ |
| while (TRUE) { |
| AUDIO_IF_LOGD("%s: thread alive\n", __FUNCTION__); |
| //reset received buffer |
| memset(inBuf, 0, sizeof(inBuf)); |
| |
| if ( (dataLen = vcm_ctl_read(inBuf, sizeof(inBuf))) < 0 ) { |
| AUDIO_IF_LOGE("%s Error while reading from audio control device return\n", __FUNCTION__); |
| sleep(2); |
| continue; |
| } |
| |
| if (dataLen == 0) { |
| AUDIO_IF_LOGD("%s Read Zero\n", __FUNCTION__); |
| sleep(2); |
| continue; |
| } |
| |
| //Dump the data been read |
| for(i = 0; i < dataLen; i++) |
| { |
| AUDIO_IF_LOGD("%s: [%d]=0x%x\n", __FUNCTION__, i, inBuf[i]); |
| } |
| |
| //Get header info |
| cmd_code = p_atc_msg->header.cmd_code; // audio is fixed as 9 |
| sub_cmd = p_atc_msg->header.sub_cmd; // 0xa: eCall, 0xc: DTMF detection |
| cmd_type = p_atc_msg->header.cmd_type; // 1: confirm, 2: indication |
| |
| //Check whether it is audio cmd |
| if(cmd_code != ATC_AUDIO_CMD) { |
| AUDIO_IF_LOGD("Warning: it is not audio command(%d), cmd_code=%d", ATC_AUDIO_CMD, cmd_code); |
| sleep(2); |
| continue; |
| } |
| |
| switch (sub_cmd) { |
| case ATC_ECALLCTL: |
| //Check whether it is eCall indication |
| if(cmd_type != CMD_TYPE_INDICATION) { |
| AUDIO_IF_LOGD("Warning: it is not eCall indication(%d), cmd_type=%d", CMD_TYPE_INDICATION, cmd_type); |
| sleep(2); |
| continue; |
| } |
| |
| p_ecall_msg = (unsigned short *) &(p_atc_msg->eCallPayload); |
| eCall_cmd = *(unsigned short *)p_ecall_msg; |
| switch(eCall_cmd){ |
| case ACIPC_CODE_AUDIO_VCM_ECALL_DATA_GET_CNF: |
| audio_if_ecall_data_status_response(p_ecall_msg); |
| break; |
| |
| case ACIPC_CODE_AUDIO_VCM_ECALL_VOICE_GET_CNF: |
| audio_if_ecall_voice_status_response(p_ecall_msg); |
| break; |
| |
| default: |
| AUDIO_IF_LOGD("Unsupport eCall_cmd: 0x%x", eCall_cmd); |
| break; |
| } |
| |
| break; |
| |
| case ATC_DTMFDETECTIONCTL: |
| DTMF_code = p_atc_msg->DTMF_code; |
| AUDIO_IF_LOGD("Got DTMF code: 0x%x", DTMF_code); |
| ret = AudioIf_BroadcastDTMFCode(DTMF_code); |
| if(ret != 0) |
| AUDIO_IF_LOGD("%s failed to broadcast DTMF code onto uBus, ret=0x%x", __FUNCTION__, ret); |
| break; |
| |
| default: |
| AUDIO_IF_LOGD("Unsupport sub_cmd: 0x%x", sub_cmd); |
| break; |
| } |
| |
| AUDIO_IF_LOGD("%s: wrote %d bytes to socket %d\n", __FUNCTION__, dataLen, sock_fd); |
| ret = write(sock_fd, inBuf, dataLen); |
| }; |
| } |
| |
| int AudioIf_BroadcastVoiceStatus(unsigned int status) |
| { |
| int ret =0; |
| |
| blob_buf_init(&VoiceStatusNotify_blob, 0); |
| blobmsg_add_u32(&VoiceStatusNotify_blob, VOICESTATUSID, status); |
| |
| ret = ubus_notify(audioIfUbusDb.ctx, &VoiceStatus_notify_obj, VoiceStatus_notify_obj.name, VoiceStatusNotify_blob.head, -1); |
| |
| return ret; |
| } |
| |
| void AudioIf_report_voice_status(void) |
| { |
| if (old_voice_status != voice_status) { |
| AUDIO_IF_LOGD("%s:Got Voice status: %d", __FUNCTION__, voice_status); |
| AudioIf_BroadcastVoiceStatus(voice_status); |
| old_voice_status = voice_status; |
| } |
| |
| return; |
| } |
| /***************************************************************************************\ |
| * Function: AudioIf_HanldeHeadsetEvent |
| * Description: This function handles headset driver reports: |
| * /sys/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hs_status |
| * /sys/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset/hk_status |
| * |
| * |
| * Jack types which can be reported.(Defined in Jack.h) |
| * enum snd_jack_types { |
| * SND_JACK_HEADPHONE = 0x0001, |
| * SND_JACK_MICROPHONE = 0x0002, |
| * SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE, |
| * SND_JACK_LINEOUT = 0x0004, |
| * SND_JACK_MECHANICAL = 0x0008, |
| * SND_JACK_VIDEOOUT = 0x0010, |
| * SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT, |
| * SND_JACK_LINEIN = 0x0020, |
| * SND_JACK_BTN_0 = 0x4000, |
| * SND_JACK_BTN_1 = 0x2000, |
| * SND_JACK_BTN_2 = 0x1000, |
| * SND_JACK_BTN_3 = 0x0800, |
| * SND_JACK_BTN_4 = 0x0400, |
| * SND_JACK_BTN_5 = 0x0200, |
| * }; |
| * Returns: void |
| \***************************************************************************************/ |
| static void AudioIf_HanldeHeadsetEvent(void) |
| { |
| int mDev, hk_status, hs_status = 0; |
| char value[32]; //written as '%d' |
| |
| /************************************************************************************* |
| * Set correct audio device in boot up phase. |
| * ----------------------------------------------------------------------------------- |
| * |
| * In boot up phase, headset driver(88pm800-headset.c) will report headset status, using UEvent. |
| * But, audio_if is started later than headset driver, and miss this UEvent. |
| * |
| * So, audio_if should check the files(HK_STATUS_DEV & HS_STATUS_DEV) created by headset driver |
| * and set the correct audio device. |
| *************************************************************************************/ |
| |
| /* Open HK_STATUS_DEV */ |
| mDev = open(HK_STATUS_DEV, O_RDONLY); |
| if (mDev < 0) |
| { |
| AUDIO_IF_LOGE("%s: Failed to open %s!err=%s\n", __FUNCTION__, HK_STATUS_DEV,strerror(errno)); |
| } |
| else |
| { |
| read(mDev, &value, sizeof(value)); |
| close(mDev); |
| hk_status = atoi(value); |
| AUDIO_IF_LOGD("%s: Success to open %s, value=%s, hk_status=%d\n", __FUNCTION__, HK_STATUS_DEV, value, hk_status); |
| } |
| |
| /* Open HS_STATUS_DEV */ |
| mDev = open(HS_STATUS_DEV, O_RDONLY); |
| if (mDev < 0) |
| { |
| AUDIO_IF_LOGE("%s: Failed to open %s!err=%s\n", __FUNCTION__, HS_STATUS_DEV,strerror(errno)); |
| } |
| else |
| { |
| read(mDev, &value, sizeof(value)); |
| close(mDev); |
| hs_status = atoi(value); |
| AUDIO_IF_LOGD("%s: Success to open %s, value=%s, hs_status=%d\n", __FUNCTION__, HS_STATUS_DEV, value, hs_status); |
| } |
| |
| /************************************************************************************* |
| * Set correct audio device according to hs_status |
| * ----------------------------------------------------------------------------------- |
| * |
| * hs_status=0, hk_status=0 ==>no headset |
| * hs_status=1, hk_status=0 ==>headphone(without mic) |
| * hs_status=3, hk_status=0 ==>headset(with mic) |
| *************************************************************************************/ |
| switch (hs_status) |
| { |
| case 1: |
| #ifdef TARGET_mmp_asr1901_KSTR901 |
| //For test |
| aud_hal_set_hw_device((int)AUDIO_DEVICE_OUT_WIRED_HEADSET); |
| AUDIO_IF_LOGD("%s: Set audio device = AUDIO_DEVICE_OUT_WIRED_HEADSET \n", __FUNCTION__); |
| #else |
| aud_hal_set_hw_device((int)AUDIO_DEVICE_OUT_WIRED_HEADPHONE); |
| AUDIO_IF_LOGD("%s: Set audio device = AUDIO_DEVICE_OUT_WIRED_HEADPHONE \n", __FUNCTION__); |
| #endif |
| break; |
| |
| case 3: |
| aud_hal_set_hw_device((int)AUDIO_DEVICE_OUT_WIRED_HEADSET); |
| AUDIO_IF_LOGD("%s: Set audio device = AUDIO_DEVICE_OUT_WIRED_HEADSET \n", __FUNCTION__); |
| break; |
| |
| case 0: |
| default: |
| /* Align with default audio device in CP audio */ |
| aud_hal_set_hw_device((int)AUDIO_DEVICE_OUT_EARPIECE); |
| AUDIO_IF_LOGD("%s: Set audio device = AUDIO_DEVICE_OUT_EARPIECE \n", __FUNCTION__); |
| break; |
| } |
| } |
| |
| |
| /***************************************************************************************\ |
| * Function: AudioIf_HandleDataFromUevent |
| * Description: This function handles Uevent |
| * For PM812 |
| * len=430, online@/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset |
| * len=424, add@/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset |
| * len=430, remove@/devices/soc.0/d4000000.apb/pxa2xx-i2c.1/i2c-1/1-0030/88pm800-headset |
| * For ALC5616 |
| * len=270, add@/devices/soc.0/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616-headset |
| * len=276, remove@/devices/soc.0/d4000000.apb/pxa2xx-i2c.0/i2c-0/0-001b/alc5616-headset |
| * Returns: void |
| \***************************************************************************************/ |
| static int AudioIf_HandleDataFromUevent(char * buf, int buflen) |
| { |
| const char * device; |
| const char * action; |
| |
| AUDIO_IF_LOGD("%s: len=%d, %s", __FUNCTION__, buflen, buf); |
| device = search_key("DRIVER", buf, buflen); |
| action = search_key("ACTION", buf, buflen); |
| |
| #if defined(CODEC_PM812) |
| if(device && (!strcmp(device, "88pm800-headset"))) |
| #elif defined(CODEC_ALC5616) |
| if(device && (!strcmp(device, "alc5616-headset"))) |
| #else |
| if(0) |
| #endif |
| { |
| AUDIO_IF_LOGD("%s: device=%s, action=%s!", __FUNCTION__, device, action); |
| |
| if(action && ( (!strcmp(action, "add"))||(!strcmp(action, "remove")))) |
| { //headset plugged or unplugged |
| AudioIf_HanldeHeadsetEvent(); |
| |
| //Make new audio device take effect, no matter it is in call or not |
| pthread_mutex_lock(&AudioIf_mutex); |
| aud_hal_select_output_device(); |
| pthread_mutex_unlock(&AudioIf_mutex); |
| } |
| } |
| |
| return 0; |
| } |
| |
| |
| static utlReturnCode_T AudioIf_ReceiveDataFromUevent(const utlEventHandlerType_T handler_type, |
| const utlEventHandlerType_T event_type, |
| const int fd, |
| const utlRelativeTime_P2c period_p, |
| void *arg_p) |
| { |
| UNUSEDPARAM(handler_type) |
| UNUSEDPARAM(event_type) |
| UNUSEDPARAM(period_p) |
| UNUSEDPARAM(arg_p) |
| |
| int ret; |
| |
| ret = read(fd, AudioIf_ueventBuffer, AudioIf_UEVENT_BUFFER_SIZE); |
| if(ret > 0) |
| AudioIf_HandleDataFromUevent(AudioIf_ueventBuffer, ret); |
| |
| return utlSUCCESS; |
| } |
| |
| |
| static int AudioIf_OpenEventLink(void) |
| { |
| while(AudioIf_ueventfd < 0) |
| { |
| AudioIf_ueventfd = open_uevent_socket(); |
| if(AudioIf_ueventfd < 0) |
| AUDIO_IF_LOGD("open EventLink error:%s\n", strerror(errno)); |
| } |
| |
| AudioIf_ueventHandler = utlSetFdEventHandler(utlEVENT_HANDLER_TYPE_READ, utlEVENT_HANDLER_PRIORITY_MEDIUM, AudioIf_ueventfd, AudioIf_ReceiveDataFromUevent, NULL); |
| |
| return AudioIf_ueventfd; |
| } |
| |
| |
| static void AudioIf_CloseEventLink(void) |
| { |
| utlDeleteEventHandler(AudioIf_ueventHandler); |
| close(AudioIf_ueventfd); |
| AudioIf_ueventfd = -1; |
| } |
| |
| |
| /*******************************************************************************\ |
| * Function: AudioIf_UTLTask |
| * Description: This function is the main task for UTL message. |
| * It will firstly set correct audio device; |
| * AudioIf_ReceiveDataFromUevent() will handle the input from UTL socket. |
| * Returns: void |
| \*******************************************************************************/ |
| static void AudioIf_UTLTask(void) |
| { |
| AudioIf_HanldeHeadsetEvent(); |
| |
| AudioIf_OpenEventLink(); |
| if (utlEventLoop(true) != utlSUCCESS) |
| { |
| AUDIO_IF_LOGE("Event loop reports failure!!!"); |
| AudioIf_CloseEventLink(); |
| return; |
| } |
| } |
| |
| |
| /*******************************************************************************\ |
| * Function: main |
| \*******************************************************************************/ |
| int main(int argc, char **argv) |
| { |
| UNUSEDPARAM(argc); |
| UNUSEDPARAM(argv); |
| |
| int ioctl_fd, err; |
| |
| /* Set log tag for logcat */ |
| set_service_log_tag("audio_if"); |
| |
| /* Wait until audiostub ready */ |
| while(1) |
| { |
| ioctl_fd = open(IOCTL_DEV, O_RDONLY); |
| if(ioctl_fd < 0) |
| { |
| err = errno; |
| AUDIO_IF_LOGE("Fail to open %s:%s\n", IOCTL_DEV, strerror(err)); |
| sleep(1); |
| continue; |
| } |
| else |
| { |
| AUDIO_IF_LOGD("Success to open %s\n", IOCTL_DEV); |
| close(ioctl_fd); |
| break; |
| } |
| } |
| |
| /* Create mutex for Ril and headset interrupt handlers */ |
| pthread_mutex_init(&AudioIf_mutex, NULL); |
| pthread_mutex_init(&AudioIf_Ubus_mutex_play, NULL); |
| pthread_mutex_init(&AudioIf_Ubus_mutex_rec, NULL); |
| |
| /* Init ubus server */ |
| if (AudioIf_uBusInit() != 0) { |
| AUDIO_IF_LOGE("%s: Init ubus server failed!", __FUNCTION__); |
| exit (-1); |
| } |
| |
| /* Init global variables */ |
| ahw_dev_ubus = audio_hal_install(); |
| if (ahw_dev_ubus == NULL) { |
| AUDIO_IF_LOGE("%s: audio_hal_install failed!", __FUNCTION__); |
| exit (-1); |
| } |
| |
| mrvl_ahw_dev_ubus = (struct mrvl_audio_device*)ahw_dev_ubus; |
| |
| /* Init ubus subscriber */ |
| AudioIf_uBusSubscribeEvents(TRUE); |
| |
| /* Create a pipe to communicate between (1)ubus thread and (2)audio HAL listner thread */ |
| if (pipe(audioIfDb.pipes_fd) != 0) { |
| AUDIO_IF_LOGE("%s: pipe failed with error %d [ %s ].", __FUNCTION__, errno, strerror(errno)); |
| exit (-1); |
| } |
| /* Create thread to listen on Audio HAL */ |
| pthread_create(&audioIfDb.tid, NULL, AudioIf_MainLoopTask, NULL); |
| /*add fd to the ubus contex. this fd is listen on audioHAL */ |
| AudioIf_uBusFdAdd(audioIfDb.pipes_fd[0]); |
| |
| /* Add notify object onto bus */ |
| ubus_add_object(audioIfUbusDb.ctx, &DTMFCode_notify_obj); |
| ubus_add_object(audioIfUbusDb.ctx, &VoiceStatus_notify_obj); |
| |
| /* Create thread to listen to UTL socket */ |
| pthread_create(&AudioIf_utid, NULL, (void *)AudioIf_UTLTask, NULL); |
| |
| /* Start uloop */ |
| AudioIf_uBusUloopRun(); |
| |
| /* Destroy mutex */ |
| pthread_mutex_destroy(&AudioIf_mutex); |
| pthread_mutex_destroy(&AudioIf_Ubus_mutex_play); |
| pthread_mutex_destroy(&AudioIf_Ubus_mutex_rec); |
| |
| /* Unregister uloop */ |
| /* Thread will get here only if uloop stopped */ |
| ubus_remove_object(audioIfUbusDb.ctx, &audioIfUbusDb.server_obj); |
| ubus_free(audioIfUbusDb.ctx); |
| uloop_done(); |
| |
| /* Unregister subscriber */ |
| AudioIf_uBusSubscribeEvents(FALSE); |
| |
| /* Unregister server */ |
| pthread_cancel(audioIfDb.tid); |
| |
| audio_hal_uninstall(); |
| exit(0); |
| } |