[Feature][ZXW-33]merge ZXW 0428 version

Change-Id: I11f167edfea428d9fab198ff00ff1364932d1b0b
diff --git a/ap/lib/libvoice/Makefile b/ap/lib/libvoice/Makefile
index e092fad..31a4d66 100644
--- a/ap/lib/libvoice/Makefile
+++ b/ap/lib/libvoice/Makefile
@@ -23,8 +23,12 @@
 #*******************************************************************************

 LIB_SHARED = libvoice.so

 LIB_STATIC = libvoice.a

-

-OBJS = voice.o 

+ifeq ($(USE_VOICE_ALSA),yes)

+OBJS = voice.o alsa_call.o voice_api.o voiceipc.o

+else

+OBJS = voice.o

+endif

+ 

 CFLAGS += -g

 LDFLAGS += -lpthread

 

@@ -33,6 +37,7 @@
 CFLAGS += -I$(zte_lib_path)/libtinyalsa/include

 CFLAGS += -I$(STAGEDIR)/include

 CFLAGS += -I$(APP_DIR)/include

+CFLAGS += -I$(LINUX_DIR)/include

 CFLAGS += -fPIC

 

 LDFLAGS_SHARED += -shared

@@ -41,14 +46,16 @@
 #*******************************************************************************

 # comp test app and 

 #*******************************************************************************	

-

-

+ifeq ($(USE_VOICE_ALSA),yes)

+EXEC_voiceipc = voiceipc

+endif

 	

 #*******************************************************************************

 # objects

 #*******************************************************************************

-

-

+ifeq ($(USE_VOICE_ALSA),yes)

+voiceipc_OBJECTS += voice_api.o voiceipc.o

+endif

 

 

 #########################for linux######################################

@@ -63,7 +70,29 @@
 LDLIBS += -L$(LIB_DIR)/libtinyalsa

 LDLIBS += -ltinyalsa

 

-all: $(LIB_STATIC) $(LIB_SHARED) 

+ifeq ($(USE_VOICE_ALSA),yes)

+all: $(LIB_STATIC) $(LIB_SHARED) $(EXEC_voiceipc)

+

+$(LIB_STATIC) : $(OBJS)

+	$(AR) rcs $(LIB_STATIC) $(OBJS)

+

+$(LIB_SHARED): $(OBJS)

+	$(CC) $(LDFLAGS) $(LDFLAGS_SHARED) -o $@ $^

+

+	

+$(EXEC_voiceipc): $(voiceipc_OBJECTS)

+	$(CC) $(LDFLAGS) -o $@ $(voiceipc_OBJECTS) -Wl,--start-group $(LDLIBS) -Wl,--end-group

+	

+clean:

+	rm -f $(voiceipc_OBJECTS) $(lib_OBJECTS) $(LIB_SHARED) $(LIB_STATIC) $(EXEC_voiceipc) *.elf *.gdb *.o core

+

+romfs:

+	$(ROMFSINST) $(LIB_SHARED) /lib/$(LIB_SHARED)

+	$(ROMFSINST) $(EXEC_voiceipc) /bin/$(EXEC_voiceipc)

+

+	cp -v $(EXEC_voiceipc)    $(APP_DIR)/test_tools/

+else

+all: $(LIB_STATIC) $(LIB_SHARED)

 

 $(LIB_STATIC) : $(OBJS)

 	$(AR) rcs $(LIB_STATIC) $(OBJS)

@@ -79,7 +108,6 @@
 

 romfs:

 	$(ROMFSINST) $(LIB_SHARED) /lib/$(LIB_SHARED)

-

-	

+endif

 

 

diff --git a/ap/lib/libvoice/alsa_call.c b/ap/lib/libvoice/alsa_call.c
new file mode 100755
index 0000000..72f82ce
--- /dev/null
+++ b/ap/lib/libvoice/alsa_call.c
@@ -0,0 +1,278 @@
+/*****************************************************************************

+** °æÈ¨ËùÓÐ (C)2015, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£

+** 

+** ÎļþÃû³Æ:     alsa_voice.c

+** Îļþ±êʶ:     

+** ÄÚÈÝÕªÒª:    

+** ʹÓ÷½·¨:     

+** 

+** ÐÞ¸ÄÈÕÆÚ        °æ±¾ºÅ      Ð޸ıê¼Ç        ÐÞ¸ÄÈË          ÐÞ¸ÄÄÚÈÝ

+** -----------------------------------------------------------------------------

+** 2019/09/25     V1.0        Create          xxq        ´´½¨

+** 

+* ******************************************************************************/

+#ifdef _USE_VOICE_ALSA

+

+#include <stdio.h>

+#include <unistd.h>

+#include <string.h>

+#include <stdlib.h>

+

+#include <stdint.h>

+//#include "volte_drv.h"

+#include <sys/ioctl.h>

+#include <fcntl.h>

+#include <tinyalsa/audio_mixer_ctrl.h>

+

+

+

+#include <stdbool.h> 

+#include "tinyalsa/asoundlib.h"

+#include "tinyalsa/audio_mixer_ctrl.h"

+//#include "audio_res_ctrl.h"

+#include "voice_lib.h"

+

+

+/**************************************************************************

+*                        ºê¶¨Òå                                           *

+**************************************************************************/

+

+//#define AVOICE_TEAK_2G_3G_DEV_NUM 3

+//#define AVOICE_SOFT_3G_DEV_NUM 4

+//#define AVOICE_4G_DEV_NUM 2

+//#define AVOICE_5G_DEV_NUM 2

+

+/**************************************************************************

+*                        ÀàÐͶ¨Òå                                         *

+**************************************************************************/

+/*

+typedef enum

+{

+    AVOICE_TEAK_2G_3G = 0,     

+    AVOICE_SOFT_3G_NB,//1

+    AVOICE_SOFT_3G_WB, //2   

+    AVOICE_4G_NB, //3                 

+    AVOICE_4G_WB, //4

+    AVOICE_5G_NB,//5    

+    AVOICE_5G_WB,//6      

+    MAX_AVOICE_MODE               

+}T_Alsa_Voice_Mode;

+*/

+

+

+/**************************************************************************

+*                        ¾Ö²¿º¯ÊýÔ­ÐÍÉùÃ÷                                 *

+**************************************************************************/

+

+/**********************************************************************************/

+/**********************************************************************************/

+/**********************************************************************************/

+

+/**********************************************************************************/

+/**************************************************************************

+*                          ¾²Ì¬È«¾Ö±äÁ¿                                   *

+**************************************************************************/

+

+

+/**************************************************************************

+*                            È«¾Öº¯Êý                                     *

+**************************************************************************/

+

+

+/**************************************************************************

+*                            ¾Ö²¿º¯Êý                                     *

+**************************************************************************/

+

+

+/****************************************************************************************************/

+/* start for testing  ctm*/

+

+/* data type for voice device  handle */

+

+struct voice_handle

+{

+    struct pcm  *pcm_voice_out;

+    struct pcm  *pcm_voice_in;

+};

+

+/* static  handle */

+static struct voice_handle voice_handle = {0};

+

+static int current_chanl = T_OUTPUT_RECEIVER;//T_OUTPUT_HEADSET;//T_OUTPUT_RECEIVER;

+static int current_vol = T_VOICE_VOL_5_LEVEL;

+static int dev_num = 1;

+static int current_mode = MAX_AVOICE_MODE;

+char* vocie_mode[]={"AVOICE_TEAK_2G_3G","AVOICE_SOFT_3G_NB","AVOICE_SOFT_3G_WB","AVOICE_4G_NB","AVOICE_4G_WB","AVOICE_5G_NB","AVOICE_5G_WB"};

+

+/*

+ * phone call   

+ */

+int alsa_voice_open(int vmode)

+{

+    int ret = 0;

+	//int status = 0;

+    struct pcm_config config_voice = {0};

+    struct mxier *voice_mixer = NULL;

+	

+	printf( "%s: start vocie_mode(%d) %s, current_mode=%d!\n",__func__,vmode,vocie_mode[vmode],current_mode);

+

+    if(vmode >= MAX_AVOICE_MODE||vmode < AVOICE_TEAK_2G_3G)

+	{

+		printf("alsa_voice_open: mode not support fail!\n");

+		return -2;

+	

+	}

+    /* open mixer dev for codec control */

+    if(!(voice_mixer = mixer_open(0))) 

+       printf("mixer open fail, file(%s), line(%d)\n", __FILE__, __LINE__);

+

+

+	if(T_OUTPUT_SPEAKER == current_chanl) {

+		mix_set_voice_path(voice_mixer,T_OUTPUT_SPEAKER);

+		

+		printf("chanl SPEAKER: mix_set_voice_path ret=%d!\n",ret);

+		mix_set_voice_vol(voice_mixer,T_VOICE_VOL_5_LEVEL);

+		

+	    printf("chanl SPEAKER: mix_set_voice_vol ret=%d!\n",ret);

+	}

+	else if (T_OUTPUT_RECEIVER == current_chanl){

+		mix_set_voice_path(voice_mixer, T_OUTPUT_RECEIVER);

+		

+		printf("chanl RECEIVER: mix_set_voice_path ret=%d!\n",ret);

+		mix_set_voice_vol(voice_mixer,T_VOICE_VOL_5_LEVEL);

+		

+	    printf("chanl RECEIVER: mix_set_voice_vol ret=%d!\n",ret);

+	}

+	else if (T_OUTPUT_HEADSET == current_chanl){

+		

+		ret= mix_set_voice_path(voice_mixer, T_OUTPUT_HEADSET);

+		

+	    printf("chanl HEADSET: mix_set_voice_path ret=%d!\n",ret);

+		ret = mix_set_voice_vol(voice_mixer,T_VOICE_VOL_5_LEVEL);

+	    printf("chanl HEADSET: mix_set_voice_vol ret=%d!\n",ret);

+		

+	}	

+	else

+	{

+		printf("alsa_voice_open: chanl not support fail!\n");

+		return -2;

+

+	}

+

+    /*close mixer */

+    mixer_close(voice_mixer);

+    

+    /* open pcm dev for data tranf*/

+    config_voice.channels = 1; /* one channel */ 

+    config_voice.rate = 8000;  /* 8K rate */ 

+    config_voice.period_count = 3; /* buffer num */

+    config_voice.period_size = 640; /* buffer size */

+    config_voice.format = PCM_FORMAT_S16_LE; /* 16-bit signed */

+    if(vmode == AVOICE_TEAK_2G_3G)

+    {

+         dev_num = AVOICE_TEAK_2G_3G_DEV_NUM;

+		 config_voice.rate = 8000;  /* 8K rate */ 

+    }

+	else if(vmode == AVOICE_SOFT_3G_NB)

+    {

+         dev_num = AVOICE_SOFT_3G_DEV_NUM;

+		 config_voice.rate = 8000;  /* 8K rate */  

+    }

+	else if(vmode == AVOICE_SOFT_3G_WB)

+    {

+         dev_num = AVOICE_SOFT_3G_DEV_NUM;

+		 config_voice.rate = 16000;  /* 16K rate */  

+    }

+	else if(vmode == AVOICE_4G_NB)

+    {

+         dev_num = AVOICE_4G_DEV_NUM;

+		 config_voice.rate = 8000;  /* 8K rate */  

+    }

+	else if(vmode == AVOICE_4G_WB)

+    {

+         dev_num = AVOICE_4G_DEV_NUM;

+		 config_voice.rate = 16000;  /* 16K rate */  

+    }

+	else if(vmode == AVOICE_5G_NB)

+    {

+         dev_num = AVOICE_5G_DEV_NUM;

+		 config_voice.rate = 8000;  /* 8K rate */  

+    }

+	else if(vmode == AVOICE_5G_WB)

+    {

+         dev_num = AVOICE_5G_DEV_NUM;

+		 config_voice.rate = 16000;  /* 16K rate */  

+    }

+	else

+	{

+		printf("alsa_voice_open: mode not support fail!\n");

+		return -2;

+	

+	}

+

+

+    if(!(voice_handle.pcm_voice_out = pcm_open(0, dev_num, PCM_OUT, &config_voice))) 

+		printf("pcm_out dev_num=%d open fail, file(%s), line(%d)\n",dev_num, __FILE__, __LINE__);

+	

+	printf("%s:pcm_open pcm_voice_out dev_num=%d end!\n",__func__,dev_num);

+		

+    if(!(voice_handle.pcm_voice_in = pcm_open(0,dev_num,PCM_IN, &config_voice))) 

+		printf("pcm_in open dev_num=%d fail, file(%s), line(%d)\n",dev_num, __FILE__, __LINE__);

+	

+	printf("%s:pcm_open pcm_voice_in dev_num=%d end!\n",__func__,dev_num);

+       

+    if(0 != pcm_prepare(voice_handle.pcm_voice_out)) 

+    	printf("pcm_out dev_num=%d prepare fail, file(%s), line(%d)\n",dev_num, __FILE__, __LINE__);

+	

+	printf("%s: pcm_voice_out pcm_prepare dev_num=%d end!\n",__func__,dev_num);

+		

+    if(0 != pcm_prepare(voice_handle.pcm_voice_in))

+   		printf("pcm_in dev_num=%d prepare fail, file(%s), line(%d)\n",dev_num, __FILE__, __LINE__);

+

+	

+	printf("%s: pcm_voice_in pcm_prepare vmode=%d dev_num=%d end!\n",__func__,vmode,dev_num);

+    current_mode = vmode;

+	printf("%s: end!\n",__func__); 

+	

+    return 0;

+}

+

+int alsa_voice_close(int vmode)

+{

+    int ret = 0;

+	printf("%s: start!\n",__func__); 

+

+    if(vmode >= MAX_AVOICE_MODE||vmode < AVOICE_TEAK_2G_3G)

+	{

+		printf("alsa_voice_close: mode not support fail!\n");

+		return -2;

+	

+	}

+

+if(voice_handle.pcm_voice_in) {

+	ret = pcm_close(voice_handle.pcm_voice_in);

+	voice_handle.pcm_voice_in = 0;

+

+	printf("pcm_close pcm_voice_in	ret=%d!\n",ret);

+}

+

+if(voice_handle.pcm_voice_out) {

+	ret = pcm_close(voice_handle.pcm_voice_out);

+	voice_handle.pcm_voice_out = 0;

+

+	printf("pcm_close pcm_voice_out  ret=%d!\n",ret);

+}

+

+

+

+

+

+	current_mode = MAX_AVOICE_MODE;

+	printf("%s: end!\n",__func__); 

+	

+    return ret; 

+}

+

+

+

+#endif

diff --git a/ap/lib/libvoice/include/voice_ipc.h b/ap/lib/libvoice/include/voice_ipc.h
new file mode 100755
index 0000000..abe83b2
--- /dev/null
+++ b/ap/lib/libvoice/include/voice_ipc.h
@@ -0,0 +1,52 @@
+#ifdef USE_CAP_SUPPORT

+

+#define VOICEIPC_OK 0

+#define VOICEIPC_ERROR -1

+#define VOICE_WAIT_MSG_FROM_CAP -2 //waitting msg from cap

+

+#define VOICE_IPC_CONTROL_CHANNEL "/dev/rpmsg6"

+#define VOICE_IPC_CONTROL_CHANNEL_SIZE 256

+

+#define VOICE_HEAD_LEN (2 * sizeof(int))

+#define VOICE_CONTROL_MAX_LEN 32

+

+enum  voice_ipc_func_type {

+	IPC_SET_VOICE_DEVICE_MODE = 0,

+    IPC_GET_VOICE_DEVICE_MODE = 1,

+    IPC_SET_RX_VOICE_VOL = 2,

+    IPC_GET_RX_VOICE_VOL = 3,

+    IPC_SET_TX_VOICE_VOL = 4,

+    IPC_GET_TX_VOICE_VOL = 5,

+    IPC_SET_TX_VOICE_MUTE_STATE = 6,

+    IPC_GET_TX_VOICE_MUTE_STATE = 7,

+    IPC_SET_RX_VOICE_MUTE_STATE = 8,

+    IPC_GET_RX_VOICE_MUTE_STATE = 9,

+    IPC_SET_LOOPBACK_ENABLE_STATE = 10,

+    IPC_GET_LOOPBACK_ENABLE_STATE = 11,

+

+    IPC_VOICE_FUNC_MAX

+};

+

+typedef struct {

+    int func_id;

+    int param_len;

+    unsigned char param[VOICE_CONTROL_MAX_LEN];

+}voice_ipc_control_msg;

+

+int voice_ipc_init(void);

+void Voice_Ctrl_Rpmsg_Recv(void);

+

+void ipc_set_voice_device_mode(voice_ipc_control_msg msg);

+void ipc_get_voice_device_mode(voice_ipc_control_msg msg);

+void ipc_set_rx_voice_vol(voice_ipc_control_msg msg);

+void ipc_get_rx_voice_vol(voice_ipc_control_msg msg);

+void ipc_set_tx_voice_vol(voice_ipc_control_msg msg);

+void ipc_get_tx_voice_vol(voice_ipc_control_msg msg);

+void ipc_set_tx_voice_mute_state(voice_ipc_control_msg msg);

+void ipc_get_tx_voice_mute_state(voice_ipc_control_msg msg);

+void ipc_set_rx_voice_mute_state(voice_ipc_control_msg msg);

+void ipc_get_rx_voice_mute_state(voice_ipc_control_msg msg);

+void ipc_set_loopback_enable_state(voice_ipc_control_msg msg);

+void ipc_get_loopback_enable_state(voice_ipc_control_msg msg);

+

+#endif

diff --git a/ap/lib/libvoice/include/voice_lib.h b/ap/lib/libvoice/include/voice_lib.h
index d2baae2..6788b77 100644
--- a/ap/lib/libvoice/include/voice_lib.h
+++ b/ap/lib/libvoice/include/voice_lib.h
@@ -8,7 +8,47 @@
 
 #ifndef __VOICE_LIB_H
 #define __VOICE_LIB_H
+#include <linux/volte_drv.h>
 
+#define AVOICE_TEAK_2G_3G_DEV_NUM 2
+#define AVOICE_SOFT_3G_DEV_NUM 4
+#define AVOICE_4G_DEV_NUM 1
+#define AVOICE_5G_DEV_NUM 1
+
+#ifdef _USE_VOICE_ALSA
+
+
+ typedef enum
+ {
+	 AVOICE_TEAK_2G_3G = 0, 	
+	 AVOICE_SOFT_3G_NB,
+	 AVOICE_SOFT_3G_WB,    
+	 AVOICE_4G_NB,					
+	 AVOICE_4G_WB, 
+	 AVOICE_5G_NB,	  
+	 AVOICE_5G_WB,		 
+	 MAX_AVOICE_MODE			   
+ }T_Alsa_Voice_Mode;
+int alsa_voice_open(int vmode);
+int alsa_voice_close(int vmode);
+
+ 
+#endif
+
+ /*  Voice process channel selection. */
+ typedef enum
+ {
+	 VP_PATH_HANDSET	= 0,
+	 VP_PATH_SPEAKER,
+	 VP_PATH_HEADSET,
+	 VP_PATH_BLUETOOTH,
+	 VP_PATH_BLUETOOTH_NO_NR,
+	 VP_PATH_HSANDSPK,
+ 
+	 VP_PATH_OFF = 255,
+ 
+	 MAX_VP_PATH = VP_PATH_OFF
+ } T_ZDrv_VpPath;
  int voice_close(T_Voice_Para *para);
  int voice_open(T_Voice_Para *para);
  int voice_Vploop(int *path);
diff --git a/ap/lib/libvoice/voice.c b/ap/lib/libvoice/voice.c
index 696c2ea..fbc8bf1 100644
--- a/ap/lib/libvoice/voice.c
+++ b/ap/lib/libvoice/voice.c
@@ -22,6 +22,8 @@
 #include <sys/ioctl.h>

 #include <fcntl.h>

 #include <tinyalsa/audio_mixer_ctrl.h>

+#include "voice_lib.h"

+

 

 #define VOICE_DEV_NAME "/dev/voice_device"

 

@@ -216,6 +218,11 @@
 			return 0;

 		}

 	}

+#ifdef _ALSA_CODEC_IN_CAP

+

+		printf("%s: i2s and codec not need config,return!\n",__func__);	

+		return 0;

+#endif

 

 

 	//open mixer dev for codec control

@@ -298,6 +305,10 @@
 			return ;

 		}

 	}

+#ifdef _ALSA_CODEC_IN_CAP

+		printf("%s: i2s and codec not need config,return!\n",__func__); 

+		return ;

+#endif

 

 

 	if (volte_pcm_voice_out) {

diff --git a/ap/lib/libvoice/voice_api.c b/ap/lib/libvoice/voice_api.c
new file mode 100755
index 0000000..e6262fb
--- /dev/null
+++ b/ap/lib/libvoice/voice_api.c
@@ -0,0 +1,423 @@
+/**

+ * @file voice_api.c

+ * @brief Implementation of the public APIs of libvoice.

+ *

+ * Copyright (C) 2023 Sanechips Technology Co., Ltd.

+ * @author 

+ * 

+ * This program is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License version 2 as

+ * published by the Free Software Foundation. £¨±ØÑ¡£ºGPLv2 Licence£©

+ *

+ */

+

+

+

+#include <stdio.h>

+#include <unistd.h>

+#include <string.h>

+#include <stdlib.h>

+

+#include <stdint.h>

+//#include "volte_drv.h"

+#include <linux/volte_drv.h>

+

+#include <sys/ioctl.h>

+#include <fcntl.h>

+#include <tinyalsa/audio_mixer_ctrl.h>

+#include "voice_lib.h"

+

+#define VOCIE_SND_CARD_NUM 0

+

+

+extern int mix_set_voice_vol(struct mixer *mixer, int volume);

+extern int mix_get_voice_vol(struct mixer *mixer, int *volume);

+extern int mix_set_tx_voice_vol(struct mixer *mixer, int volume);

+extern int mix_get_tx_voice_vol(struct mixer *mixer, int *volume);

+extern int mix_set_voice_mute(struct mixer *mixer, bool enable);

+extern int mix_get_voice_mute(struct mixer *mixer, int *enable);

+extern int mix_set_rx_voice_mute(struct mixer *mixer, bool enable);

+extern int mix_get_rx_voice_mute(struct mixer *mixer, int *enable);

+extern int mix_set_voice_path(struct mixer *mixer, int path);

+extern int mix_set_vp_path(struct mixer *mixer, char path);

+extern int mix_get_vp_path(struct mixer *mixer, int *path);

+extern int mix_get_voice_path(struct mixer *mixer, int *path);

+

+

+	

+#define VOCIE_SND_CARD_NUM 0

+	

+	

+	

+//设置voice音频设备模式 dev_mode:handset,speaker,headset	0 表示成功ï¼?其它表示有错è¯?

+int set_voice_device_mode(int dev_mode)

+{

+

+	struct mixer *voice_mixer = NULL;

+	printf("%s: start dev_mode=%d!\n",__func__, dev_mode);

+

+	if ((dev_mode < T_OUTPUT_HANDSET ) ||(dev_mode >= T_OUTPUT_MAX)){

+		printf("%s: dev_mode not support, dev_mode=%d!\n",__func__, dev_mode);

+		return -1;

+	}

+

+	//open mixer dev for  control

+	voice_mixer = mixer_open(VOCIE_SND_CARD_NUM);

+	if (!voice_mixer) {

+		printf("voice_mixer open failed!\n");

+		return -1;

+	}

+

+	//config mixer dev

+	mix_set_voice_path(voice_mixer, dev_mode);

+

+	//close mixer

+	mixer_close(voice_mixer);

+	voice_mixer = NULL;

+

+

+	return 0;

+	

+	

+}

+

+

+

+int sc_audio_set_voice_device_mode(int dev_mode)

+{

+

+	struct mixer *voice_mixer = NULL;

+	printf("%s: start dev_mode=%d!\n",__func__, dev_mode);

+

+	if ((dev_mode < T_OUTPUT_HANDSET ) ||(dev_mode >= T_OUTPUT_MAX)){

+		printf("%s: dev_mode not support, dev_mode=%d!\n",__func__, dev_mode);

+		return -1;

+	}

+

+	//open mixer dev for  control

+	voice_mixer = mixer_open(VOCIE_SND_CARD_NUM);

+	if (!voice_mixer) {

+		printf("voice_mixer open failed!\n");

+		return -1;

+	}

+#ifdef _ALSA_CODEC_IN_CAP

+	mix_set_vp_path(voice_mixer,dev_mode);

+

+#else

+	//config mixer dev

+	mix_set_voice_path(voice_mixer, dev_mode);

+#endif

+

+

+	//close mixer

+	mixer_close(voice_mixer);

+	voice_mixer = NULL;

+

+

+	return 0;

+	

+	

+}

+

+

+int sc_audio_get_voice_device_mode(int *p_dev_mode)

+{

+	struct mixer *voice_mixer = NULL;

+	printf("%s: start!\n",__func__);

+

+	//open mixer dev for  control

+	voice_mixer = mixer_open(VOCIE_SND_CARD_NUM);

+	if (!voice_mixer) {

+		printf("voice_mixer open failed!\n");

+		return -1;

+	}

+

+	//config mixer dev

+	mix_get_vp_path(voice_mixer, p_dev_mode);

+

+	

+	if((*p_dev_mode < T_OUTPUT_HANDSET ) ||(*p_dev_mode >= T_OUTPUT_MAX)){

+		printf("%s: dev_mode not support, *p_dev_mode=%d!\n",__func__, *p_dev_mode);

+		//return -1;

+	}

+	printf("%s: start *p_dev_mode=%d!\n",__func__, *p_dev_mode);

+

+	//close mixer

+	mixer_close(voice_mixer);

+	voice_mixer = NULL;

+

+	return 0;

+	

+}

+

+

+int sc_audio_set_rx_voice_vol(int vol)

+{

+	struct mixer *voice_mixer = NULL;

+	printf("%s: start vol=%d!\n",__func__, vol);

+

+	if ((vol < 0 ) ||(vol > 11)){

+		printf("%s: vol not support, vol=%d!\n",__func__, vol);

+		return -1;

+	}

+

+	//open mixer dev for  control

+	voice_mixer = mixer_open(VOCIE_SND_CARD_NUM);

+	if (!voice_mixer) {

+		printf("voice_mixer open failed!\n");

+		return -1;

+	}

+

+	//config mixer dev

+	mix_set_voice_vol(voice_mixer, vol);

+

+	//close mixer

+	mixer_close(voice_mixer);

+	voice_mixer = NULL;

+

+

+	return 0;

+

+

+	

+	

+}

+

+

+

+int sc_audio_get_rx_voice_vol(int     * p_vol)

+{

+	struct mixer *voice_mixer = NULL;

+

+	printf("%s: start!\n",__func__);

+

+	//open mixer dev for  control

+	voice_mixer = mixer_open(VOCIE_SND_CARD_NUM);

+	if (!voice_mixer) {

+		printf("voice_mixer open failed!\n");

+		return -1;

+	}

+

+	//config mixer dev

+	mix_get_voice_vol(voice_mixer, p_vol);

+	

+

+	if ((*p_vol < 0 ) ||(*p_vol > 11)){

+		printf("%s: vol not support, *p_vol=%d!\n",__func__, *p_vol);

+		//return -1;

+	}

+	printf("%s:  *p_vol=%d!\n",__func__, *p_vol);

+

+	//close mixer

+	mixer_close(voice_mixer);

+	voice_mixer = NULL;

+

+

+	return 0;

+

+	

+	

+}

+

+

+

+int sc_audio_set_tx_voice_vol(int vol)

+{

+	struct mixer *voice_mixer = NULL;

+	printf("%s: start vol=%d!\n",__func__, vol);

+

+	if ((vol < 0 ) ||(vol > 11)){

+		printf("%s: vol not support, vol=%d!\n",__func__, vol);

+		return -1;

+	}

+

+	//open mixer dev for  control

+	voice_mixer = mixer_open(VOCIE_SND_CARD_NUM);

+	if (!voice_mixer) {

+		printf("voice_mixer open failed!\n");

+		return -1;

+	}

+

+	//config mixer dev

+	mix_set_tx_voice_vol(voice_mixer, vol);

+

+	//close mixer

+	mixer_close(voice_mixer);

+	voice_mixer = NULL;

+

+

+	return 0;

+	

+	

+}

+

+

+

+int sc_audio_get_tx_voice_vol(int  *p_vol)

+{

+	struct mixer *voice_mixer = NULL;

+	printf("%s: start!\n",__func__);

+

+

+	//open mixer dev for  control

+	voice_mixer = mixer_open(VOCIE_SND_CARD_NUM);

+	if (!voice_mixer) {

+		printf("voice_mixer open failed!\n");

+		return -1;

+	}

+

+	//config mixer dev

+	mix_get_tx_voice_vol(voice_mixer, p_vol);

+	

+

+	if((*p_vol < 0 ) ||(*p_vol > 5)){

+		printf("%s: vol not support, *p_vol=%d!\n",__func__, *p_vol);

+		//return -1;

+	}

+	printf("%s:  *p_vol=%d!\n",__func__, *p_vol);

+

+	//close mixer

+	mixer_close(voice_mixer);

+	voice_mixer = NULL;	

+    return 0;	

+}

+

+

+

+int sc_audio_set_tx_voice_mute_state(int mute         )

+{

+	struct mixer *voice_mixer = NULL;

+	printf("%s: start mute=%d!\n",__func__, mute);

+

+	if((mute != 0 ) &&(mute != 1)) {

+		printf("%s: mute not support, mute=%d!\n",__func__, mute);

+		return -1;

+	}

+

+	//open mixer dev for  control

+	voice_mixer = mixer_open(VOCIE_SND_CARD_NUM);

+	if (!voice_mixer) {

+		printf("voice_mixer open failed!\n");

+		return -1;

+	}

+

+	//config mixer dev

+	mix_set_voice_mute(voice_mixer, mute);

+

+	//close mixer

+	mixer_close(voice_mixer);

+	voice_mixer = NULL;

+    return 0;	

+	

+}

+

+int sc_audio_get_tx_voice_mute_state(int *p_mute)

+{

+	struct mixer *voice_mixer = NULL;

+

+	printf("%s: start!\n",__func__);

+

+	//open mixer dev for  control

+	voice_mixer = mixer_open(VOCIE_SND_CARD_NUM);

+	if (!voice_mixer) {

+		printf("voice_mixer open failed!\n");

+		return -1;

+	}

+

+	//config mixer dev

+	mix_get_voice_mute(voice_mixer, p_mute);

+	

+

+	if((*p_mute != 0 ) &&(*p_mute != 1)) {

+		printf("%s: *p_mute not support, *p_mute=%d!\n",__func__, *p_mute);

+		//close mixer

+	    mixer_close(voice_mixer);

+	    voice_mixer = NULL;	

+		return -1;

+	}

+	printf("%s:  *p_mute=%d!\n",__func__, *p_mute);

+

+	//close mixer

+	mixer_close(voice_mixer);

+	voice_mixer = NULL;	

+

+    return 0;

+}

+

+

+

+

+

+

+

+int sc_audio_set_rx_voice_mute_state(int mute) 

+{

+	struct mixer *voice_mixer = NULL;

+	printf("%s: start mute=%d!\n",__func__, mute);

+

+	if((mute != 0 ) &&(mute != 1)) {

+		printf("%s: mute not support, mute=%d!\n",__func__, mute);

+		return -1;

+	}

+

+	//open mixer dev for  control

+	voice_mixer = mixer_open(VOCIE_SND_CARD_NUM);

+	if (!voice_mixer) {

+		printf("voice_mixer open failed!\n");

+		return -1;

+	}

+

+	//config mixer dev

+	mix_set_rx_voice_mute(voice_mixer, mute);

+

+	//close mixer

+	mixer_close(voice_mixer);

+	voice_mixer = NULL;

+    return 0;	

+	

+}

+

+

+int sc_audio_get_rx_voice_mute_state(int *p_mute){

+	struct mixer *voice_mixer = NULL;

+

+	printf("%s: start!\n",__func__);

+

+	//open mixer dev for  control

+	voice_mixer = mixer_open(VOCIE_SND_CARD_NUM);

+	if (!voice_mixer) {

+		printf("voice_mixer open failed!\n");

+		return -1;

+	}

+

+	//config mixer dev

+	mix_get_rx_voice_mute(voice_mixer, p_mute);

+	

+	if((*p_mute != 0 ) &&(*p_mute != 1)) {

+

+		printf("%s: *p_mute not support, *p_mute=%d!\n",__func__, *p_mute);

+		//close mixer

+	    mixer_close(voice_mixer);

+	    voice_mixer = NULL;

+		return -1;

+	}

+	printf("%s:  *p_mute=%d!\n",__func__, *p_mute);

+

+	//close mixer

+	mixer_close(voice_mixer);

+	voice_mixer = NULL;	

+

+    return 0;

+

+}

+

+int sc_audio_set_loopback_enable_state(int enable)

+{

+    return 0;

+}

+

+int sc_audio_get_loopback_enable_state(int *p_enable)

+{

+    return 0;

+}

+

diff --git a/ap/lib/libvoice/voiceipc.c b/ap/lib/libvoice/voiceipc.c
new file mode 100755
index 0000000..198fe19
--- /dev/null
+++ b/ap/lib/libvoice/voiceipc.c
@@ -0,0 +1,402 @@
+#ifdef USE_CAP_SUPPORT

+#include <stdio.h>

+#include <unistd.h>

+#include <string.h>

+#include <stdlib.h>

+#include <stdint.h>

+#include <sys/ioctl.h>

+#include <fcntl.h>

+#include "voice_ipc.h"

+#include "linux/rpmsg_zx29.h"

+

+extern int sc_audio_set_voice_device_mode(int dev_mode);

+extern int sc_audio_get_voice_device_mode(int *p_dev_mode);

+extern int sc_audio_set_rx_voice_vol(int vol);

+extern int sc_audio_get_rx_voice_vol(int     * p_vol);

+extern int sc_audio_set_tx_voice_vol(int vol);

+extern int sc_audio_get_tx_voice_vol(int  *p_vol);

+extern int sc_audio_set_tx_voice_mute_state(int mute         );

+extern int sc_audio_get_tx_voice_mute_state(int *p_mute);

+extern int sc_audio_set_rx_voice_mute_state(int mute);

+extern int sc_audio_get_rx_voice_mute_state(int *p_mute);

+extern int sc_audio_set_loopback_enable_state(int enable);

+extern int sc_audio_get_loopback_enable_state(int *p_enable);

+

+int voice_ipc_fd = -1;

+voice_ipc_control_msg voice_ctrl_recvmsg[IPC_VOICE_FUNC_MAX] = {0};

+

+void ipc_set_voice_device_mode(voice_ipc_control_msg msg)

+{

+    int ret = VOICEIPC_OK;

+    int msg_len = 0;

+    int dev_mode = 0;

+

+    //memcpy(&dev_mode, msg.param, msg.param_len);

+    dev_mode = *((int *)msg.param);

+    ret = sc_audio_set_voice_device_mode(dev_mode);

+

+    //msg.func_id不变

+    msg.param_len = sizeof(int);

+    memcpy(msg.param, &ret, msg.param_len);

+    msg_len = VOICE_HEAD_LEN + msg.param_len;

+

+    ret = write(voice_ipc_fd, &msg, msg_len);

+    

+    if (0 >= ret){

+		printf("%s: write error(%d)!\n", __func__, ret);

+	}

+}

+

+void ipc_get_voice_device_mode(voice_ipc_control_msg msg)

+{

+    int ret = VOICEIPC_OK;

+    int msg_len = 0;

+    int *p_dev_mode = NULL;

+

+    p_dev_mode = (int *)msg.param;

+    ret = sc_audio_get_voice_device_mode(p_dev_mode);

+	

+    //msg.func_id不变

+    msg.param_len = sizeof(int);

+    memcpy(msg.param, &ret, msg.param_len);

+    msg_len = VOICE_HEAD_LEN + msg.param_len;

+

+    ret = write(voice_ipc_fd, &msg, msg_len);

+    

+    if (0 >= ret){

+		printf("%s: write error(%d)!\n", __func__, ret);

+	}

+}

+

+void ipc_set_rx_voice_vol(voice_ipc_control_msg msg)

+{

+    int ret = VOICEIPC_OK;

+    int msg_len = 0;

+    int vol = 0;

+

+    //memcpy(&dev_mode, msg.param, msg.param_len);

+    vol = *((int *)msg.param);

+    ret = sc_audio_set_rx_voice_vol(vol);

+

+    //msg.func_id不变

+    msg.param_len = sizeof(int);

+    memcpy(msg.param, &ret, msg.param_len);

+    msg_len = VOICE_HEAD_LEN + msg.param_len;

+

+    ret = write(voice_ipc_fd, &msg, msg_len);

+    

+    if (0 >= ret){

+		printf("%s: write error(%d)!\n", __func__, ret);

+	}

+}

+

+void ipc_get_rx_voice_vol(voice_ipc_control_msg msg)

+{

+    int ret = VOICEIPC_OK;

+    int msg_len = 0;

+    int *p_vol = NULL;

+

+    p_vol = (int *)msg.param;

+    ret = sc_audio_get_rx_voice_vol(p_vol);

+	

+    //msg.func_id不变

+    msg.param_len = sizeof(int);

+    memcpy(msg.param, &ret, msg.param_len);

+    msg_len = VOICE_HEAD_LEN + msg.param_len;

+

+    ret = write(voice_ipc_fd, &msg, msg_len);

+    

+    if (0 >= ret){

+		printf("%s: write error(%d)!\n", __func__, ret);

+	}

+}

+

+void ipc_set_tx_voice_vol(voice_ipc_control_msg msg)

+{

+    int ret = VOICEIPC_OK;

+    int msg_len = 0;

+    int vol = 0;

+

+    //memcpy(&dev_mode, msg.param, msg.param_len);

+    vol = *((int *)msg.param);

+    ret = sc_audio_set_tx_voice_vol(vol);

+

+    //msg.func_id不变

+    msg.param_len = sizeof(int);

+    memcpy(msg.param, &ret, msg.param_len);

+    msg_len = VOICE_HEAD_LEN + msg.param_len;

+

+    ret = write(voice_ipc_fd, &msg, msg_len);

+    

+    if (0 >= ret){

+		printf("%s: write error(%d)!\n", __func__, ret);

+	}

+}

+

+void ipc_get_tx_voice_vol(voice_ipc_control_msg msg)

+{

+    int ret = VOICEIPC_OK;

+    int msg_len = 0;

+    int *p_vol = NULL;

+

+    p_vol = (int *)msg.param;

+    ret = sc_audio_get_tx_voice_vol(p_vol);

+	

+    //msg.func_id不变

+    msg.param_len = sizeof(int);

+    memcpy(msg.param, &ret, msg.param_len);

+    msg_len = VOICE_HEAD_LEN + msg.param_len;

+

+    ret = write(voice_ipc_fd, &msg, msg_len);

+    

+    if (0 >= ret){

+		printf("%s: write error(%d)!\n", __func__, ret);

+	}

+}

+

+void ipc_set_tx_voice_mute_state(voice_ipc_control_msg msg)

+{

+    int ret = VOICEIPC_OK;

+    int msg_len = 0;

+    int mute = 0;

+

+    //memcpy(&dev_mode, msg.param, msg.param_len);

+    mute = *((int *)msg.param);

+    ret = sc_audio_set_tx_voice_mute_state(mute);

+

+    //msg.func_id不变

+    msg.param_len = sizeof(int);

+    memcpy(msg.param, &ret, msg.param_len);

+    msg_len = VOICE_HEAD_LEN + msg.param_len;

+

+    ret = write(voice_ipc_fd, &msg, msg_len);

+    

+    if (0 >= ret){

+		printf("%s: write error(%d)!\n", __func__, ret);

+	}

+}

+

+void ipc_get_tx_voice_mute_state(voice_ipc_control_msg msg)

+{

+    int ret = VOICEIPC_OK;

+    int msg_len = 0;

+    int *p_mute = NULL;

+

+    p_mute = (int *)msg.param;

+    ret = sc_audio_get_tx_voice_mute_state(p_mute);

+	

+    //msg.func_id不变

+    msg.param_len = sizeof(int);

+    memcpy(msg.param, &ret, msg.param_len);

+    msg_len = VOICE_HEAD_LEN + msg.param_len;

+

+    ret = write(voice_ipc_fd, &msg, msg_len);

+    

+    if (0 >= ret){

+		printf("%s: write error(%d)!\n", __func__, ret);

+	}

+}

+

+void ipc_set_rx_voice_mute_state(voice_ipc_control_msg msg)

+{

+    int ret = VOICEIPC_OK;

+    int msg_len = 0;

+    int mute = 0;

+

+    //memcpy(&dev_mode, msg.param, msg.param_len);

+    mute = *((int *)msg.param);

+    ret = sc_audio_set_rx_voice_mute_state(mute);

+

+    //msg.func_id不变

+    msg.param_len = sizeof(int);

+    memcpy(msg.param, &ret, msg.param_len);

+    msg_len = VOICE_HEAD_LEN + msg.param_len;

+

+    ret = write(voice_ipc_fd, &msg, msg_len);

+    

+    if (0 >= ret){

+		printf("%s: write error(%d)!\n", __func__, ret);

+	}

+}

+

+void ipc_get_rx_voice_mute_state(voice_ipc_control_msg msg)

+{

+    int ret = VOICEIPC_OK;

+    int msg_len = 0;

+    int *p_mute = NULL;

+

+    p_mute = (int *)msg.param;

+    ret = sc_audio_get_rx_voice_mute_state(p_mute);

+	

+    //msg.func_id不变

+    msg.param_len = sizeof(int);

+    memcpy(msg.param, &ret, msg.param_len);

+    msg_len = VOICE_HEAD_LEN + msg.param_len;

+

+    ret = write(voice_ipc_fd, &msg, msg_len);

+    

+    if (0 >= ret){

+		printf("%s: write error(%d)!\n", __func__, ret);

+	}

+}

+

+void ipc_set_loopback_enable_state(voice_ipc_control_msg msg)

+{

+    int ret = VOICEIPC_OK;

+    int msg_len = 0;

+    int enable = 0;

+

+    //memcpy(&dev_mode, msg.param, msg.param_len);

+    enable = *((int *)msg.param);

+    ret = sc_audio_set_loopback_enable_state(enable);

+

+    //msg.func_id不变

+    msg.param_len = sizeof(int);

+    memcpy(msg.param, &ret, msg.param_len);

+    msg_len = VOICE_HEAD_LEN + msg.param_len;

+

+    ret = write(voice_ipc_fd, &msg, msg_len);

+    

+    if (0 >= ret){

+		printf("%s: write error(%d)!\n", __func__, ret);

+	}

+}

+

+void ipc_get_loopback_enable_state(voice_ipc_control_msg msg)

+{

+    int ret = VOICEIPC_OK;

+    int msg_len = 0;

+    int *p_enable = NULL;

+

+    p_enable = (int *)msg.param;

+    ret = sc_audio_get_loopback_enable_state(p_enable);

+	

+    //msg.func_id不变

+    msg.param_len = sizeof(int);

+    memcpy(msg.param, &ret, msg.param_len);

+    msg_len = VOICE_HEAD_LEN + msg.param_len;

+

+    ret = write(voice_ipc_fd, &msg, msg_len);

+    

+    if (0 >= ret){

+		printf("%s: write error(%d)!\n", __func__, ret);

+	}

+}

+

+void voice_msg_proc(voice_ipc_control_msg msg)

+{

+	switch(msg.func_id){

+		case IPC_SET_VOICE_DEVICE_MODE:

+			ipc_set_voice_device_mode(voice_ctrl_recvmsg[msg.func_id]);

+			break;

+		case IPC_GET_VOICE_DEVICE_MODE:

+			ipc_get_voice_device_mode(voice_ctrl_recvmsg[msg.func_id]);

+			break;

+        case IPC_SET_RX_VOICE_VOL:

+			ipc_set_rx_voice_vol(voice_ctrl_recvmsg[msg.func_id]);

+			break;

+        case IPC_GET_RX_VOICE_VOL:

+			ipc_get_rx_voice_vol(voice_ctrl_recvmsg[msg.func_id]);

+			break;

+        case IPC_SET_TX_VOICE_VOL:

+			ipc_set_tx_voice_vol(voice_ctrl_recvmsg[msg.func_id]);

+			break;

+        case IPC_GET_TX_VOICE_VOL:

+			ipc_get_tx_voice_vol(voice_ctrl_recvmsg[msg.func_id]);

+			break;

+        case IPC_SET_TX_VOICE_MUTE_STATE:

+			ipc_set_tx_voice_mute_state(voice_ctrl_recvmsg[msg.func_id]);

+			break;

+        case IPC_GET_TX_VOICE_MUTE_STATE:

+			ipc_get_tx_voice_mute_state(voice_ctrl_recvmsg[msg.func_id]);

+			break;

+        case IPC_SET_RX_VOICE_MUTE_STATE:

+			ipc_set_rx_voice_mute_state(voice_ctrl_recvmsg[msg.func_id]);

+			break;

+        case IPC_GET_RX_VOICE_MUTE_STATE:

+			ipc_get_rx_voice_mute_state(voice_ctrl_recvmsg[msg.func_id]);

+			break;

+        case IPC_SET_LOOPBACK_ENABLE_STATE:

+			ipc_set_loopback_enable_state(voice_ctrl_recvmsg[msg.func_id]);

+			break;

+        case IPC_GET_LOOPBACK_ENABLE_STATE:

+			ipc_get_loopback_enable_state(voice_ctrl_recvmsg[msg.func_id]);

+			break;

+		default:

+			printf("%s: msg func_id(%d) error\n", __func__, msg.func_id);

+			break;

+	}

+}

+

+void Voice_Ctrl_Rpmsg_Recv(void)

+{

+    int read_len = 0;

+    voice_ipc_control_msg tmpbuf = {0};

+    

+    for(;;){

+        read_len = 0;

+		read_len = read(voice_ipc_fd, &tmpbuf, (VOICE_HEAD_LEN + VOICE_CONTROL_MAX_LEN));

+        if (0 >= read_len){

+			continue;

+		}

+

+        //最后再改变func_id,确保其他地方判断func_id改变后有数据可读

+        memcpy(voice_ctrl_recvmsg[tmpbuf.func_id].param, tmpbuf.param, tmpbuf.param_len);

+        voice_ctrl_recvmsg[tmpbuf.func_id].param_len = tmpbuf.param_len;

+        voice_ctrl_recvmsg[tmpbuf.func_id].func_id = tmpbuf.func_id;

+        

+        voice_msg_proc(voice_ctrl_recvmsg[tmpbuf.func_id]);

+    }

+}

+

+int voice_ipc_init(void) //通道初始化

+{

+    voice_ipc_fd = open(VOICE_IPC_CONTROL_CHANNEL, O_RDWR);

+

+    if(0 > voice_ipc_fd){

+        printf("%s: open the channel(%s) error!\n", __func__, VOICE_IPC_CONTROL_CHANNEL);

+        return VOICEIPC_ERROR;

+    }

+

+    if(0 > ioctl(voice_ipc_fd, RPMSG_CREATE_CHANNEL, VOICE_IPC_CONTROL_CHANNEL_SIZE)){

+        printf("%s: ioctl RPMSG_CREATE_CHANNEL fail!\n", __func__);

+        close(voice_ipc_fd);

+        voice_ipc_fd = -1;

+        return VOICEIPC_ERROR;

+    }

+    

+    if(0 > ioctl(voice_ipc_fd, RPMSG_SET_INT_FLAG, NULL)){ //写中断

+        printf("%s: ioctl RPMSG_SET_INT_FLAG fail!\n", __func__);

+        close(voice_ipc_fd);

+        voice_ipc_fd = -1;

+        return VOICEIPC_ERROR;

+    }

+    

+    if(0 > ioctl(voice_ipc_fd, RPMSG_CLEAR_POLL_FLAG, NULL)){ //阻塞方式读数据

+        printf("%s: ioctl RPMSG_CLEAR_POLL_FLAG fail!\n", __func__);

+        close(voice_ipc_fd);

+        voice_ipc_fd = -1;

+        return VOICEIPC_ERROR;

+    }

+    return VOICEIPC_OK;

+}

+

+int main(int argc, char **argv)

+{

+    int ret = 0;

+    

+    ret = voice_ipc_init();

+    

+    if(ret < 0){

+        printf("voice_ipc_init error!\n");

+        return -1;

+    }

+

+    printf("voice_ipc_init %s create success!\n", VOICE_IPC_CONTROL_CHANNEL);

+    

+    Voice_Ctrl_Rpmsg_Recv();

+    

+    return 0;

+}

+

+#endif