/***************************************************************************** | |
** °æÈ¨ËùÓÐ (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=%d.\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(_VBUFF_IN_SINGLE_CORE) || defined(_VBUFF_IN_MULTI_CORE) | |
printf("%s: ap use voice buffer,return!\n",__func__); | |
return 0; | |
#endif | |
#if defined(_ALSA_CODEC_IN_CAP) && defined(_USE_ALSA_AT_INTF) | |
printf("%s:_ALSA_CODEC_IN_CAP and at intf!\n",__func__); | |
printf("%s:ap i2s and codec not need config,return!\n",__func__); | |
return 0; | |
#elif defined(_ALSA_CODEC_IN_CAP) | |
printf("%s:_ALSA_CODEC_IN_CAP!\n",__func__); | |
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 | |
printf("%s:ap do mixer and pcm opt!\n",__func__); | |
//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(_VBUFF_IN_SINGLE_CORE) || defined(_VBUFF_IN_MULTI_CORE) | |
printf("%s: use voice buffer,return!\n",__func__); | |
return 0; | |
#endif | |
#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; | |
} | |
} | |
int voice_SetVoiceProcess(int *vp) | |
{ | |
int ret = 0; | |
int fd = -1; | |
printf("%s: start vp=%d!\n",__func__,*vp); | |
fd = open(VOICE_DEV_NAME, O_RDONLY); | |
if (fd < 0) { | |
printf("%s: open voice device error.\n",__func__); | |
return -1; | |
} | |
ret = ioctl(fd, VOICE_IOCTL_SET_VP, vp); | |
if (ret) { | |
printf("%s: ret=%d,vp=%d.\n",__func__, ret, *vp); | |
close(fd); | |
return -1; | |
} | |
close(fd); | |
return 0; | |
} | |
int voice_GetVoiceProcess(void) | |
{ | |
int ret = 0; | |
int fd = -1; | |
int vp = 0; | |
fd = open(VOICE_DEV_NAME, O_RDONLY); | |
if (fd < 0) { | |
printf("%s: open voice device error.\n",__func__); | |
return -1; | |
} | |
ret = ioctl(fd, VOICE_IOCTL_GET_VP, &vp); | |
if (ret) { | |
printf("%s: ret=%d,vp=%d.\n",__func__, ret, vp); | |
close(fd); | |
return -1; | |
} | |
close(fd); | |
printf("%s: vp=%d!\n",__func__,vp); | |
return vp; | |
} | |
int voice_SetVoiceBuffer(T_VoiceBuf_Para *vb) | |
{ | |
int ret = 0; | |
int fd = -1; | |
printf("%s: start enable=%d,type=%d!\n",__func__,vb->enable,vb->type); | |
fd = open(VOICE_DEV_NAME, O_RDONLY); | |
if (fd < 0) { | |
printf("%s: open voice device error.\n",__func__); | |
return -1; | |
} | |
ret = ioctl(fd, VOICE_IOCTL_SET_VBUF, vb); | |
if (ret) { | |
printf("%s: ret=%d.\n",__func__, ret); | |
close(fd); | |
return -1; | |
} | |
close(fd); | |
return 0; | |
} | |
int voice_GetVoiceBuffer(T_VoiceBuf_Para *vb) | |
{ | |
int ret = 0; | |
int fd = -1; | |
fd = open(VOICE_DEV_NAME, O_RDONLY); | |
if (fd < 0) { | |
printf("%s: open voice device error.\n",__func__); | |
return -1; | |
} | |
ret = ioctl(fd, VOICE_IOCTL_GET_VBUF, vb); | |
if (ret) { | |
printf("%s: ret=%d.\n",__func__, ret); | |
close(fd); | |
return -1; | |
} | |
close(fd); | |
printf("%s: start fs=%d enable=%d,type=%d!\n",__func__,vb->fs,vb->enable,vb->type); | |
return ret; | |
} | |