[Feature][T106][Voice]Add liblynq-qser-voice

Change-Id: Ic14fa5a28602224e5a926306db43c606fa9f48a6
diff --git a/cap/zx297520v3/sources/meta-zxic-custom/conf/distro/vehicle_dc.conf b/cap/zx297520v3/sources/meta-zxic-custom/conf/distro/vehicle_dc.conf
index 2a2af37..16e7981 100755
--- a/cap/zx297520v3/sources/meta-zxic-custom/conf/distro/vehicle_dc.conf
+++ b/cap/zx297520v3/sources/meta-zxic-custom/conf/distro/vehicle_dc.conf
@@ -152,7 +152,8 @@
         liblynq-sim \
         liblynq-network \
         liblynq-sms \
-        liblynq-data \	
+        liblynq-data \
+        liblynq-qser-voice \
 	"
 zxic_lib += "${@bb.utils.contains('CONFIG_TEL_API_SUPPORT', 'RIL', 'libbinder libril', 'libtelsvr', d)}"
 
diff --git a/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/liblynq-qser-voice/liblynq-qser-voice.bb b/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/liblynq-qser-voice/liblynq-qser-voice.bb
new file mode 100644
index 0000000..1265fc0
--- /dev/null
+++ b/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/liblynq-qser-voice/liblynq-qser-voice.bb
@@ -0,0 +1,46 @@
+inherit externalsrc package
+
+DESCRIPTION = "liblynq-qser-voice"
+LICENSE = "CLOSED"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+DEPENDS += "liblynq-log liblynq-call"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/lynq/lib/liblynq-qser-voice/"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+BB_INCLUDE_ADD = "--sysroot=${STAGING_DIR_HOST}"
+BB_LDFLAGS_ADD = "--sysroot=${STAGING_DIR_HOST} -Wl,--hash-style=gnu"
+#Parameters passed to do_compile()
+FILES_${PN} = "${base_libdir}/*.so "
+
+FILES_${PN}-dev = "/test \
+                   ${includedir}"
+
+FILES_${PN}-doc = "/doc"
+
+FILES_${PN}-dbg ="${base_bindir}/.debug \
+                  ${base_libdir}/.debug \
+                  ${base_sbindir}/.debug"
+
+INSANE_SKIP_${PN} += "already-stripped"
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+
+
+#INHIBIT_PACKAGE_STRIP = "1"
+do_compile () {
+		oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -Wl,--hash-style=gnu -DTELEPHONYWARE"
+}
+
+do_install () {
+    oe_runmake install ROOT=${D}
+	
+    if [ -d "${WORKONSRC}" ] ; then
+        install -d ${D}${includedir}/
+        cp -af ${S}include/ ${D}${includedir}/
+    fi 
+}
+
+addtask bachclean
+do_bachclean () {
+    oe_runmake clean
+}
\ No newline at end of file
diff --git a/cap/zx297520v3/src/lynq/lib/liblynq-qser-voice/include/lynq-qser-voice.h b/cap/zx297520v3/src/lynq/lib/liblynq-qser-voice/include/lynq-qser-voice.h
new file mode 100644
index 0000000..528acc0
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/lib/liblynq-qser-voice/include/lynq-qser-voice.h
@@ -0,0 +1,133 @@
+/**
+ *@file     qser_voice.h
+ *@date     2017-11-30
+ *@author   
+ *@brief    
+ */
+
+
+#ifndef __LYNQ_QSER_VOICE_H__
+#define __LYNQ_QSER_VOICE_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+    E_QSER_VCALL_EXTERNAL_SLOT_1,
+    E_QSER_VCALL_EXTERNAL_SLOT_2,
+    E_QSER_VCALL_EMBEDDED,
+    E_QSER_VCALL_REMOTE,
+    E_QSER_VCALL_ID_MAX
+}E_QSER_VCALL_ID_T;
+
+typedef enum 
+{
+    E_QSER_VOICE_CALL_STATE_INCOMING      = 0x0000, /**< MT incoming; CC setup. */
+    E_QSER_VOICE_CALL_STATE_DIALING       = 0x0001, /**< Dialing state. */
+    E_QSER_VOICE_CALL_STATE_ALERTING      = 0x0002, /**< MT call waiting; MO alterting. */
+    E_QSER_VOICE_CALL_STATE_ACTIVE        = 0x0003, /**< Call is active. */
+    E_QSER_VOICE_CALL_STATE_HOLDING       = 0x0004, /**< Call is on hold. */
+    E_QSER_VOICE_CALL_STATE_END           = 0x0005, /**< Call is disconnected. */
+    E_QSER_VOICE_CALL_STATE_WAITING       = 0x0006, /**< Call is waiting. */
+}qser_voice_call_state_t;
+
+typedef enum 
+{
+    E_QSER_VOICE_CALL_WAITING_VOICE_ENABLED       = 0, /**<  Voice call waiting enabled. */
+    E_QSER_VOICE_CALL_WAITING_DISABLED            = 1, /**<  Voice call waiting disabled. */
+}E_QSER_VOICE_CALL_WAITING_SERVICE_T;
+
+typedef struct 
+{
+    E_QSER_VOICE_CALL_WAITING_SERVICE_T   waiting_service;
+}qser_voice_call_waiting_service_t;
+
+typedef qser_voice_call_state_t E_QSER_VOICE_CALL_STATE_T;
+
+typedef uint32_t voice_client_handle_type;
+
+/* Callback function registered via QSER_Voice_Call_AddStateHandler;
+   This will be called if any stated changed of call_id
+*/
+typedef void (*QSER_VoiceCall_StateHandlerFunc_t)
+(
+    int                     caLOCAL_C_INCLUDESll_id,
+    char*                   phone_num,
+    E_QSER_VOICE_CALL_STATE_T state,
+    void                    *contextPtr
+);
+
+/* Init voice module and return h_voice, this should be called before any other APIs */
+int qser_voice_call_client_init(voice_client_handle_type  *ph_voice);
+
+/* DeInit voice module and release resources, this should be called at last */
+int qser_voice_call_client_deinit(voice_client_handle_type h_voice);
+
+/* Add callback function, if any call state changed, handlerPtr will be called to notify App */
+int qser_voice_call_addstatehandler(voice_client_handle_type          h_voice,
+                                  QSER_VoiceCall_StateHandlerFunc_t   handlerPtr,
+                                  void*                             contextPtr);
+
+/* Remove callback function, won't receive any notify anymore */
+int qser_voice_call_removestatehandle(voice_client_handle_type       h_voice);
+
+/* Start call and return call_id, this can be used in the later */
+int qser_voice_call_start(voice_client_handle_type    h_voice,
+                        E_QSER_VCALL_ID_T             simId,
+                        char*                       phone_number,   ///< [IN] Destination identifier for the voice
+                        int                         *call_id);       ///< [OUT] call id
+
+/* End call of call_id, which returned by QSER_Voice_Call_Start or callback func register via QSER_Voice_Call_AddStateHandler */
+int qser_voice_call_end(  voice_client_handle_type    h_voice,
+                        int                         call_id);        ///< [IN] call id, return by QSER_Voice_Start
+
+/* Answer the call of call_id, which returned by callback func register via QSER_Voice_Call_AddStateHandler */
+int qser_voice_call_answer(voice_client_handle_type    h_voice,
+                         int                         call_id );
+
+int qser_voice_call_hold( voice_client_handle_type    h_voice);
+
+int qser_voice_call_unhold(voice_client_handle_type    h_voice);
+
+//Set voice call waiting
+int qser_voice_call_setwaiting
+( 
+    int                                 h_voice, 
+    qser_voice_call_waiting_service_t e_service
+);
+
+//Get voice call waiting status
+int qser_voice_call_getwaitingsatus
+(
+    int                                 h_voice, 
+    qser_voice_call_waiting_service_t *pe_service
+);
+
+
+/*
+Usage 1 (register callback and wait for new call in, then answer): 
+1, QSER_Voice_Call_Client_Init
+2, QSER_Voice_Call_AddStateHandler(pf_cb)
+3, wait for new call arrive, pf_cb will pass the call_id to app.
+4, QSER_Voice_Call_Answer(call_id)
+5, QSER_Voice_Call_End
+6, QSER_Voice_Call_Client_Deinit
+
+
+Usage 2 (call out): 
+1, QSER_Voice_Call_Client_Init
+2, QSER_Voice_Call_AddStateHandler(pf_cb)
+3, QSER_Voice_Call_Start
+4, QSER_Voice_Call_End
+5, QSER_Voice_Call_Client_Deinit
+
+
+*/
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __QSER_VOICE_H__
+
diff --git a/cap/zx297520v3/src/lynq/lib/liblynq-qser-voice/lynq-qser-voice.cpp b/cap/zx297520v3/src/lynq/lib/liblynq-qser-voice/lynq-qser-voice.cpp
new file mode 100755
index 0000000..faa1a1b
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/lib/liblynq-qser-voice/lynq-qser-voice.cpp
@@ -0,0 +1,220 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <liblog/lynq_deflog.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <libcall/lynq_call.h>
+
+#include "lynq-qser-voice.h"
+
+#define USER_LOG_TAG "LYNQ_QSER_CALL"
+
+#define RESULT_OK (0)
+#define RESULT_ERROR (-1)
+
+static pthread_t s_lynq_voice_tid = -1;
+static QSER_VoiceCall_StateHandlerFunc_t   s_voice_cb = NULL;
+static int s_voice_thread_status = 0;
+
+ typedef enum {
+     LYNQ_CALL_ACTIVE = 0,
+     LYNQ_CALL_HOLDING = 1,
+     LYNQ_CALL_DIALING = 2,    /* MO call only */
+     LYNQ_CALL_ALERTING = 3,   /* MO call only */
+     LYNQ_CALL_INCOMING = 4,   /* MT call only */
+     LYNQ_CALL_WAITING = 5,    /* MT call only */
+     /*warren add for T800 platform 2022/04/26 start*/
+     LYNQ_CALL_END = 6,         /*CALL END*/
+     /*warren add for T800 platform 2022/04/26 end*/
+}lynq_call_state_t;
+
+
+void *voice_thread_recv(void *context)
+{
+    int handle = 0;
+    int call_state;
+    int toa;
+    int direction;
+    char addr[64];
+    E_QSER_VOICE_CALL_STATE_T voice_state;
+    while (s_voice_thread_status)
+    {
+        lynq_wait_call_state_change(&handle);
+        lynq_get_current_call_state(&handle,&call_state,&toa,&direction,addr);
+        if (call_state == LYNQ_CALL_ACTIVE)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_ACTIVE;
+        }
+        else if(call_state == LYNQ_CALL_HOLDING)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_HOLDING;
+        }
+        else if(call_state == LYNQ_CALL_DIALING)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_DIALING;
+        }
+        else if(call_state == LYNQ_CALL_ALERTING)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_ALERTING;
+        }
+        else if(call_state == LYNQ_CALL_INCOMING)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_INCOMING;
+        }
+        else if(call_state == LYNQ_CALL_WAITING)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_WAITING;
+        }
+        else if(call_state == LYNQ_CALL_END)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_END;
+        }
+        else
+        {
+            LYERRLOG("unknow call state");
+            continue;
+        }
+        if (s_voice_cb != NULL)
+        {
+            s_voice_cb(handle,addr,voice_state,context);
+        }
+    }
+    return NULL;
+}
+
+int qser_voice_call_client_init(voice_client_handle_type  *ph_voice)
+{   
+    if(NULL == ph_voice)
+    {
+        LYERRLOG("input error");
+        return RESULT_ERROR;
+    }
+    *ph_voice = (voice_client_handle_type)getpid();
+    return lynq_init_call(*ph_voice);
+}
+
+int qser_voice_call_client_deinit(voice_client_handle_type h_voice)
+{
+    if (NULL == h_voice)
+    {
+        LYERRLOG("init first");
+        return RESULT_ERROR;
+    }
+    return lynq_deinit_call();
+}
+
+int qser_voice_call_addstatehandler(voice_client_handle_type          h_voice,
+                                  QSER_VoiceCall_StateHandlerFunc_t   handlerPtr,
+                                  void*                             contextPtr)
+{
+    if(h_voice == 0 || handlerPtr== NULL)
+    {
+        LYERRLOG("input error");
+        return RESULT_ERROR;
+    }
+    if (s_voice_cb != NULL)
+    {
+        LYERRLOG("The existing state handle does not need to be added");
+        return RESULT_ERROR;
+    }
+    s_voice_cb = handlerPtr;
+    s_voice_thread_status = 1;
+    int rt = pthread_create(&s_lynq_voice_tid, NULL, voice_thread_recv, contextPtr);
+    if(rt < 0)
+    {
+        LYDBGLOG("qser_voice_call_addstatehandler pthread_create error!!!\n");
+        s_voice_cb = NULL;
+        s_voice_thread_status = 0;
+        s_lynq_voice_tid = -1;
+        return RESULT_ERROR;
+    }
+    return RESULT_OK;
+}
+
+int qser_voice_call_removestatehandle(voice_client_handle_type h_voice)
+{
+    int ret;
+    if (s_lynq_voice_tid != -1)
+    {
+        ret = pthread_cancel(s_lynq_voice_tid);
+        LYDBGLOG("pthread cancel ret = %d",ret);
+    }
+    if (s_lynq_voice_tid != -1)
+    {
+        ret = pthread_join(s_lynq_voice_tid,NULL);
+        LYDBGLOG("pthread cancel ret = %d",ret);
+        s_lynq_voice_tid = -1;
+    }
+    s_voice_thread_status = 0;
+    s_voice_cb == NULL;
+    return RESULT_OK;
+}
+
+int qser_voice_call_start(voice_client_handle_type    h_voice,
+                        E_QSER_VCALL_ID_T             simId,
+                        char*                       phone_number,
+                        int                         *call_id)
+{
+    if(h_voice == 0 || NULL == phone_number || NULL == call_id)
+    {
+        LYERRLOG("qser_voice_call_start input error");
+        return RESULT_ERROR;
+    }
+    return lynq_call(call_id,phone_number);
+}  
+
+int qser_voice_call_end(voice_client_handle_type h_voice,int call_id)
+{
+    if(h_voice == 0 || call_id <= 0)
+    {
+        LYERRLOG("qser_voice_call_end input error");
+        return RESULT_ERROR;
+    }
+    return lynq_call_hungup(&call_id);
+}
+
+int qser_voice_call_answer(voice_client_handle_type h_voice,int call_id)
+{
+    if(h_voice == 0 || call_id <= 0)
+    {
+        LYERRLOG("qser_voice_call_answer input error");
+        return RESULT_ERROR;
+    }
+    return lynq_call_answer();
+}
+
+int qser_voice_call_getwaitingsatus(int h_voice,qser_voice_call_waiting_service_t *pe_service)
+{
+    LYINFLOG("To be completed");
+    return RESULT_OK;
+}
+
+int qser_voice_call_setwaiting(int h_voice, qser_voice_call_waiting_service_t e_service)
+{
+    LYINFLOG("To be completed");
+    return RESULT_OK;
+}
+
+int qser_voice_call_hold(voice_client_handle_type h_voice)
+{
+    if (h_voice == 0)
+    {
+        LYERRLOG("init first");
+        return RESULT_ERROR;
+    }
+    return lynq_switch_waiting_or_holding_and_active();
+}
+
+int qser_voice_call_unhold(voice_client_handle_type h_voice)
+{
+    if (h_voice == 0)
+    {
+        LYERRLOG("init first");
+        return RESULT_ERROR;
+    }
+    return lynq_switch_waiting_or_holding_and_active();
+}
\ No newline at end of file
diff --git a/cap/zx297520v3/src/lynq/lib/liblynq-qser-voice/makefile b/cap/zx297520v3/src/lynq/lib/liblynq-qser-voice/makefile
new file mode 100644
index 0000000..b5b7d36
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/lib/liblynq-qser-voice/makefile
@@ -0,0 +1,66 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+                -std=gnu++14 \
+                -g -Os \
+                -flto \
+                -fPIC \
+                -fpermissive \
+
+
+
+$(warning ################# lynq qser sms demo ROOT: $(ROOT),includedir:$(includedir))
+LOCAL_PATH   = .
+
+LOCAL_C_INCLUDES = \
+  -I. \
+  -I$(LOCAL_PATH)/include/ \
+  -I$(LOCAL_PATH)/ \
+  -I$(ROOT)$(includedir)/liblog \
+  -I$(ROOT)$(includedir)/libcall \
+
+
+LOCAL_LIBS := \
+    -L. \
+    -lstdc++ \
+    -lcutils \
+    -lutils \
+    -lbinder \
+    -lpthread \
+    -llynq-log \
+    -llynq-call \
+
+
+SOURCES = $(wildcard *.cpp)
+
+EXECUTABLE = liblynq-qser-voice.so
+
+OBJECTS=$(SOURCES:.cpp=.o)
+
+
+.PHONY: build clean install pack_rootfs 
+all: build
+$(EXECUTABLE): $(OBJECTS)
+	$(CXX) -shared -Wl,--no-undefined $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o : %.cpp
+	$(CXX) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+build:  $(EXECUTABLE)
+	$(warning ########## build $(EXECUTABLE)  ##########)
+install:
+	mkdir -p $(ROOT)$(base_libdir)/
+	install $(EXECUTABLE) $(ROOT)$(base_libdir)/
+	mkdir -p $(ROOT)$(includedir)/$(NAME)/sdk
+pack_rootfs:
+	mkdir -p $(PACK_INITRAMFS_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_INITRAMFS_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_INITRAMFS_TO)$(base_libdir)/$(EXECUTABLE)
+	mkdir -p $(PACK_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_TO)$(base_libdir)/$(EXECUTABLE)
+.PHONY: clean
+clean:
+	$(RM) $(OBJECTS) $(EXECUTABLE)
+	-find . -name "*.o" -delete