| /***************************************************************************** | |
| ** °æÈ¨ËùÓÐ (C)2015, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£ | |
| ** | |
| ** ÎļþÃû³Æ: voice.c | |
| ** Îļþ±êʶ: | |
| ** ÄÚÈÝÕªÒª: | |
| ** ʹÓ÷½·¨: | |
| ** | |
| ** ÐÞ¸ÄÈÕÆÚ °æ±¾ºÅ Ð޸ıê¼Ç ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ | |
| ** ----------------------------------------------------------------------------- | |
| ** 2019/09/25 V1.0 Create xxq ´´½¨ | |
| ** | |
| * ******************************************************************************/ | |
| #include <stdio.h> | |
| #include <unistd.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #include <stdint.h> | |
| #include <linux/volte_drv.h> | |
| #include <sys/ioctl.h> | |
| #include <fcntl.h> | |
| #include <tinyalsa/audio_mixer_ctrl.h> | |
| #include "voice_lib.h" | |
| #include "voice_ipc.h" | |
| #define VOICE_DEV_NAME "/dev/voice_device" | |
| typedef struct { | |
| int fd; | |
| unsigned int state; // 0 close;1 open | |
| T_Voice_Para vpara; | |
| } T_voiceInfo; | |
| T_voiceInfo *voiceinfo = NULL; | |
| static int slic_flag = 0; | |
| static int slic_flag_already = 0;// 0 not get ,1 already get | |
| struct pcm *volte_pcm_voice_out = NULL; | |
| struct pcm *volte_pcm_voice_in = NULL; | |
| #if 0 | |
| T_Voice_Para gsmhwpara = { | |
| 8000, //8000;16000 | |
| 0, //// 0 gsm;1 td;2 wcdma;3 lte | |
| 0//0 hardware dsp;1 soft amr lib | |
| }; | |
| T_Voice_Para tdnbhwpara = { | |
| 8000, //8000;16000 | |
| 1, //// 0 gsm;1 td;2 wcdma;3 lte | |
| 0,//0 amr-nb;1 amr-wb | |
| 0//0 hardware dsp;1 soft amr lib | |
| }; | |
| T_Voice_Para tdnbsfpara = { | |
| 8000, //8000;16000 | |
| 1, //// 0 gsm;1 td;2 wcdma;3 lte | |
| 0,//0 amr-nb;1 amr-wb | |
| 1//0 hardware dsp;1 soft amr lib | |
| }; | |
| T_Voice_Para tdwbsfpara = { | |
| 8000, //8000;16000 | |
| 1, //// 0 gsm;1 td;2 wcdma;3 lte | |
| 1,//0 amr-nb;1 amr-wb | |
| 1//0 hardware dsp;1 soft amr lib | |
| }; | |
| #endif | |
| //static volatile int voiceinfo.fd = 0; | |
| int voice_open(T_Voice_Para *para) | |
| { | |
| int ret = 0; | |
| if (!para) { | |
| printf("voice: open para is NULL.\n"); | |
| return -1; | |
| } | |
| voiceinfo = calloc(1, sizeof(T_voiceInfo)); | |
| if (!voiceinfo) { | |
| printf("voice: open calloc fail!\n"); | |
| return -1; | |
| } | |
| voiceinfo->vpara = *para; | |
| voiceinfo->fd = open(VOICE_DEV_NAME, O_RDONLY); | |
| if (voiceinfo->fd < 0) { | |
| printf("voice lib: open voice device error.\n"); | |
| free(voiceinfo); | |
| return -1; | |
| } | |
| ret = ioctl(voiceinfo->fd, VOICE_IOCTL_START, para); | |
| if (ret) { | |
| printf("voice lib: voice start fd=%d,ret=%d.\n", voiceinfo->fd, ret); | |
| goto err; | |
| } | |
| printf("voice open end !\n"); | |
| return 0; | |
| err: | |
| close(voiceinfo->fd); | |
| free(voiceinfo); | |
| printf("voice open err end !\n"); | |
| return -1; | |
| } | |
| int voice_close(T_Voice_Para *para) | |
| { | |
| int ret = 0; | |
| if (!voiceinfo) { | |
| printf("voice: close voiceinfo is NUll!\n"); | |
| return 0; | |
| } | |
| ret = ioctl(voiceinfo->fd, VOICE_IOCTL_STOP, para); | |
| if (ret) { | |
| printf("voice lib: voice stop fd=%d,ret=%d.\n", voiceinfo->fd, ret); | |
| } | |
| if (voiceinfo->fd >= 0) { | |
| close(voiceinfo->fd); | |
| } | |
| voiceinfo->fd = -1; | |
| free(voiceinfo); | |
| voiceinfo = NULL; | |
| printf("voice close end !\n"); | |
| return 0; | |
| } | |
| int voice_Vploop(int *path) | |
| { | |
| int ret = 0; | |
| int fd = -1; | |
| printf("voice_Vploop: start path=%d!\n",*path); | |
| fd = open(VOICE_DEV_NAME, O_RDONLY); | |
| if (fd < 0) { | |
| printf("voice_Vploop: open voice device error.\n"); | |
| return -1; | |
| } | |
| ret = ioctl(fd, VOICE_IOCTL_VPLOOP, path); | |
| if (ret) { | |
| printf("voice_Vploop: ret=%d,path=%p.\n", ret, path); | |
| close(fd); | |
| return -1; | |
| } | |
| close(fd); | |
| return 0; | |
| } | |
| int voice_GetSlicFlag(void) | |
| { | |
| int ret = 0; | |
| int fd = -1; | |
| int flag = 0; | |
| printf("voice_GetSlicFlag: start!\n"); | |
| fd = open(VOICE_DEV_NAME, O_RDONLY); | |
| if (fd < 0) { | |
| printf("voice_GetSlicFlag: open voice device error.\n"); | |
| return -1; | |
| } | |
| ret = ioctl(fd, VOICE_IOCTL_GET_SLIC_USE_FLAG, &flag); | |
| if (ret) { | |
| printf("voice_GetSlicFlag: ret=%d,flag=%d.\n", ret, flag); | |
| close(fd); | |
| return -1; | |
| } | |
| close(fd); | |
| slic_flag_already = 1; | |
| return flag; | |
| } | |
| static T_ZDrvVoice_Cfg s_cfgParam = {0}; | |
| static int cur_vmode = MAX_AVOICE_MODE; | |
| int zDrvVolte_PreOpen(T_ZDrvVolte_Cfg *cfgParam) | |
| { | |
| struct mixer *voice_mixer = NULL; | |
| struct pcm_config config_voice = {0}; | |
| int ret = 0; | |
| printf(" voice lib zDrvVolte_PreOpen!\n"); | |
| if (slic_flag_already == 1) { | |
| printf(" voice slic flag already get, slic_flag=%d!\n", slic_flag); | |
| if (slic_flag == 1) { | |
| return 0; | |
| } | |
| } else { | |
| slic_flag = voice_GetSlicFlag(); | |
| printf(" voice slic flag get, slic_flag=%d!\n", slic_flag); | |
| if (slic_flag == 1) { | |
| return 0; | |
| } | |
| } | |
| #if defined(_ALSA_CODEC_IN_CAP) && defined(_USE_ALSA_AT_INTF) | |
| printf("%s: i2s and codec not need config,return!\n",__func__); | |
| return 0; | |
| #elif defined(_ALSA_CODEC_IN_CAP) | |
| if(cfgParam->clock_rate == 8000){ | |
| ret = cap_alsa_voice_open(AVOICE_4G_NB); | |
| printf("%s:cap_alsa_voice_open clock_rate(%d) ret=%d!\n",__func__,cfgParam->clock_rate,ret); | |
| cur_vmode = AVOICE_4G_NB; | |
| } | |
| else if(cfgParam->clock_rate == 16000){ | |
| ret = cap_alsa_voice_open(AVOICE_4G_WB); | |
| printf("%s:cap_alsa_voice_open clock_rate(%d) ret=%d!\n",__func__,cfgParam->clock_rate,ret); | |
| cur_vmode = AVOICE_4G_WB; | |
| } | |
| else{ | |
| printf("%s:cap_alsa_voice_open clock_rate(%d) not support!\n",__func__,cfgParam->clock_rate); | |
| return -2; | |
| } | |
| s_cfgParam = *cfgParam; | |
| return ret; | |
| #endif | |
| //open mixer dev for codec control | |
| voice_mixer = mixer_open(0); | |
| if (!voice_mixer) { | |
| printf("voice_mixer open failed!\n"); | |
| return -1; | |
| } | |
| //config mixer dev | |
| mix_set_voice_path(voice_mixer, T_OUTPUT_SPEAKER); | |
| mix_set_voice_vol(voice_mixer, T_VOICE_VOL_3_LEVEL); | |
| //close mixer | |
| mixer_close(voice_mixer); | |
| voice_mixer = NULL; | |
| //open pcm dev for data tranf | |
| config_voice.channels = cfgParam->channel_count; | |
| config_voice.rate = cfgParam->clock_rate; | |
| //buffer num | |
| config_voice.period_count = 3; | |
| //buffer size | |
| config_voice.period_size = cfgParam->samples_per_frame * cfgParam->bits_per_sample / 8; | |
| //16-bit signed | |
| config_voice.format = PCM_FORMAT_S16_LE; | |
| //card 0 dev 1 | |
| //23G card 0 dev 2 | |
| volte_pcm_voice_out = pcm_open(0, 1, PCM_OUT, &config_voice); | |
| if (!pcm_is_ready(volte_pcm_voice_out)) { | |
| printf("volte_pcm_voice_out open failed!\n"); | |
| goto err_ret; | |
| } | |
| volte_pcm_voice_in = pcm_open(0, 1, PCM_IN, &config_voice); | |
| if (!pcm_is_ready(volte_pcm_voice_in)) { | |
| printf("volte_pcm_voice_in open failed!\n"); | |
| goto err_ret; | |
| } | |
| if (0 != pcm_prepare(volte_pcm_voice_out)) { | |
| printf("volte_pcm_voice_out pcm_prepare failed!\n"); | |
| goto err_ret; | |
| } | |
| if (0 != pcm_prepare(volte_pcm_voice_in)) { | |
| printf("volte_pcm_voice_in pcm_prepare failed!\n"); | |
| goto err_ret; | |
| } | |
| return 0; | |
| err_ret: | |
| pcm_close(volte_pcm_voice_out); | |
| volte_pcm_voice_out = NULL; | |
| if (volte_pcm_voice_in) { | |
| pcm_close(volte_pcm_voice_in); | |
| volte_pcm_voice_in = NULL; | |
| } | |
| return -1; | |
| } | |
| void zDrvVolte_PreClose(void) | |
| { | |
| int ret = 0; | |
| printf(" voice lib zDrvVolte_PreClose!\n"); | |
| if (slic_flag_already == 1) { | |
| printf(" voice slic flag already get, slic_flag=%d!\n", slic_flag); | |
| if (slic_flag == 1) { | |
| return; | |
| } | |
| } else { | |
| slic_flag = voice_GetSlicFlag(); | |
| printf(" voice slic flag get, slic_flag=%d!\n", slic_flag); | |
| if (slic_flag == 1) { | |
| return; | |
| } | |
| } | |
| #if defined(_ALSA_CODEC_IN_CAP) && defined(_USE_ALSA_AT_INTF) | |
| printf("%s: i2s and codec not need config,return!\n",__func__); | |
| return ; | |
| #elif defined(_ALSA_CODEC_IN_CAP) | |
| if(s_cfgParam.clock_rate == 8000){ | |
| ret = cap_alsa_voice_close(AVOICE_4G_NB); | |
| printf("%s:cap_alsa_voice_close clock_rate(%d) ret=%d!\n",__func__,s_cfgParam.clock_rate,ret); | |
| } | |
| else if(s_cfgParam.clock_rate == 16000){ | |
| ret = cap_alsa_voice_close(AVOICE_4G_WB); | |
| printf("%s:cap_alsa_voice_close clock_rate(%d) ret=%d!\n",__func__,s_cfgParam.clock_rate,ret); | |
| } | |
| else{ | |
| printf("%s:cap_alsa_voice_close clock_rate(%d) not support!\n",__func__,s_cfgParam.clock_rate); | |
| } | |
| return; | |
| #endif | |
| if (volte_pcm_voice_out) { | |
| pcm_close(volte_pcm_voice_out); | |
| volte_pcm_voice_out = NULL; | |
| } | |
| if (volte_pcm_voice_in) { | |
| pcm_close(volte_pcm_voice_in); | |
| volte_pcm_voice_in = NULL; | |
| } | |
| } | |