[Feature][T106_eSDK]update from T106-V2.01.01.02P56U06.AP.15.11_CAP.15.11.01 to T106-V2.01.01.02P56U09.AP.17.02_CAP.17.02.02 -- patch
Only Configure: No
Affected branch: master
Affected module: unknow
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: Yes
Doc Update: No
Change-Id: Ic7183ee7e5a24ab23cd725f8b630385ea268cc1b
diff --git a/patch/15.11_17.02/code/15.11_17.02.diff b/patch/15.11_17.02/code/15.11_17.02.diff
new file mode 100755
index 0000000..e61d134
--- /dev/null
+++ b/patch/15.11_17.02/code/15.11_17.02.diff
@@ -0,0 +1,15280 @@
+From afee7eee3c07cb19d97bd7a5da74979da4488f55 Mon Sep 17 00:00:00 2001
+From: l.yang <l.yang@mobiletek.cn>
+Date: Thu, 10 Oct 2024 15:01:10 +0800
+Subject: [PATCH] [Feature][T106_eSDK]update from T106-V2.01.01.02P56U06.AP.15.11_CAP.15.11.01 to T106-V2.01.01.02P56U06.AP.17.02_CAP.17.02.02 -- code
+
+Only Configure: No
+Affected branch: master
+Affected module: unknow
+Is it affected on both ZXIC and MTK: only ZXIC
+Self-test: Yes
+Doc Update: No
+
+Change-Id: Ib96b45ce27a9cc1e8e774c42334dfb86aa0da634
+---
+
+diff --git a/esdk/layers/meta-zxic-custom/conf/distro/vehicle_dc_ref.conf b/esdk/layers/meta-zxic-custom/conf/distro/vehicle_dc_ref.conf
+index 55ad19c..e90d0da 100755
+--- a/esdk/layers/meta-zxic-custom/conf/distro/vehicle_dc_ref.conf
++++ b/esdk/layers/meta-zxic-custom/conf/distro/vehicle_dc_ref.conf
+@@ -85,7 +85,8 @@
+ #DISTRO_FEATURES += "MMI_LCD"
+ #语音控制
+ DISTRO_FEATURES += "voice_alsa"
+-#DISTRO_FEATURES += "use_voice_buffer"
++DISTRO_FEATURES += "use_voice_buffer"
++#DISTRO_FEATURES += "voice_at"
+
+ #cap_oem.img
+ DISTRO_FEATURES += " oemfs "
+@@ -138,8 +139,10 @@
+ CUSTOM_MACRO += " -D_USE_CODEC_ES8311 "
+ CUSTOM_MACRO += "${@bb.utils.contains('DISTRO_FEATURES', 'voice_alsa', '-D_USE_VOICE_ALSA', '', d)}"
+ CUSTOM_MACRO += "${@bb.utils.contains('DISTRO_FEATURES', 'use_voice_buffer', '-D_USE_VOICE_BUFFER', '', d)}"
++CUSTOM_MACRO += "${@bb.utils.contains('DISTRO_FEATURES', 'voice_at', '-D_USE_VOICE_AT', '', d)}"
+ #CONFIG_VB_TRANSMIT_INTF = "RTP"
+ #CONFIG_VB_TRANSMIT_INTF = "USB"
++CONFIG_VB_TRANSMIT_INTF = "NULL"
+ CUSTOM_MACRO += "${@bb.utils.contains('CONFIG_VB_TRANSMIT_INTF', 'RTP', '-D_VB_TRANSMIT_INTF_RTP', '', d)}"
+ CUSTOM_MACRO += "${@bb.utils.contains('CONFIG_VB_TRANSMIT_INTF', 'USB', '-D_VB_TRANSMIT_INTF_USB', '', d)}"
+ #wifi 配置
+@@ -153,6 +156,8 @@
+ CONFIG_TEL_API_SUPPORT = "RIL"
+
+ CUSTOM_MACRO += "${@bb.utils.contains('CONFIG_TEL_API_SUPPORT', 'BL', '-D_USE_BL', '', d)}"
++
++#RIL AT通道支持RPMSG模式
+ CUSTOM_MACRO += "${@bb.utils.contains('CONFIG_TEL_API_SUPPORT', 'RIL', '-DZXIC_ATCHN_RPMSG_MODE', '', d)}"
+ CUSTOM_MACRO += "${@bb.utils.contains('CONFIG_TEL_API_SUPPORT', 'RIL', '-DUSE_CUSTOM_YK', '', d)}"
+
+@@ -163,6 +168,9 @@
+ CONFIG_MSMSVR_CODEC_TYPE = "NONE"
+ CUSTOM_MACRO += "${@bb.utils.contains('CONFIG_MSMSVR_CODEC_TYPE', 'FFMPEG', '-D_USE_FFMPEG', '', d)}"
+
++#是否使用新的信号强度命令
++CONFIG_USE_NEW_SIGNAL_STRENGTH = "yes"
++
+ # app and libs 配置
+ #normal的版本应用及库
+ zxic_lib += "\
+@@ -454,11 +462,11 @@
+ MOBILETEK_ADB_LOGIN = "NO"
+
+ #cz.li@20240221 add for MOBILETEK_GNSS_UPDATE_ENABLE value: "yes","no"
+-MOBILETEK_GNSS_UPDATE_ENABLE = "no"
++MOBILETEK_GNSS_UPDATE_ENABLE = "yes"
+
+ #xf.li@20240716 add for MOBILETEK_LOG_ENCRYPT value: "enable","disable"
+ MOBILETEK_LOG_ENCRYPT = "disable"
+
+ LYNQ_CONFIG_COMMITID = "e2a3410390ff0ad762462ccb6af8faa5e16dcd61"
+-LYNQ_CONFIG_VERSION = "T106-V2.01.01.02P56U06.AP.15.11_CAP.15.11"
+-LYNQ_CONFIG_SW_VERSION = "T106-V2.01.01.02P56U06.AP.15.11_CAP.15.11.01"
++LYNQ_CONFIG_VERSION = "T106-V2.01.01.02P56U09.AP.17.02_CAP.17.02.02"
++LYNQ_CONFIG_SW_VERSION = "T106-V2.01.01.02P56U09.AP.17.02_CAP.17.02"
+diff --git a/esdk/layers/meta-zxic-custom/conf/lynq_base.conf b/esdk/layers/meta-zxic-custom/conf/lynq_base.conf
+index be8f374..e391546 100755
+--- a/esdk/layers/meta-zxic-custom/conf/lynq_base.conf
++++ b/esdk/layers/meta-zxic-custom/conf/lynq_base.conf
+@@ -67,6 +67,6 @@
+ #OEMAPP_CFG value:"PLATFORM","GSW"
+ MOBILETEK_OEMAPP_CFG = "PLATFORM"
+
+-LYNQ_CONFIG_COMMITID = "7495f7cb5c99259bdcbb21cdf89b9e0324ac444b"
+-LYNQ_CONFIG_VERSION = "T106-V2.01.01.02P56U06.AP.15.11_CAP.15.11"
+-LYNQ_CONFIG_SW_VERSION = "T106-V2.01.01.02P56U06.AP.15.11_CAP.15.11.01"
++LYNQ_CONFIG_COMMITID = "9aea88bb79cfb2fae9ddab87f8307126d618aec2"
++LYNQ_CONFIG_VERSION = "T106-V2.01.01.02P56U09.AP.17.02_CAP.17.02.02"
++LYNQ_CONFIG_SW_VERSION = "T106-V2.01.01.02P56U09.AP.17.02_CAP.17.02"
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc/fs/normal/rootfs/etc_ro/default/default_parameter_sys b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc/fs/normal/rootfs/etc_ro/default/default_parameter_sys
+index 636cedd..eade5dc 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc/fs/normal/rootfs/etc_ro/default/default_parameter_sys
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc/fs/normal/rootfs/etc_ro/default/default_parameter_sys
+@@ -439,7 +439,6 @@
+ NGECALL_FORTEST=0
+ CUSTOMER_FLAG=0
+ #for volte end
+-DEBUG_INFO_DISABLE=0
+ DEBUG_INFO_FILE_PATH=/mnt/userdata
+ DEBUG_INFO_FILE_NUM=2
+ DEBUG_INFO_FILE_TOTAL_SIZE=1
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc/fs/normal/rootfs/etc_ro/default/default_parameter_user b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc/fs/normal/rootfs/etc_ro/default/default_parameter_user
+index 7839262..5234be8 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc/fs/normal/rootfs/etc_ro/default/default_parameter_user
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc/fs/normal/rootfs/etc_ro/default/default_parameter_user
+@@ -78,6 +78,10 @@
+ br_ipchange_flag=
+ br_node=usblan0+zvnet0
+ br_node_cap=zvnet0
++br_node_num=
++br_node0=
++br_node1=
++br_node2=
+ clat_fake_subnet=192.0.168.0
+ clat_frag_collect_timeout=300
+ clat_local_mapping_timeout=300
+@@ -490,7 +494,10 @@
+ gw_in_cap=0
+ #yes-on no-off
+ cc_at_debug=no
+-xlat_enable=0
++xlat_enable=1
+ ecallmode=2
+ telog_path_cap=
+ telog_path=
++zpsstate_detect=1
++zpsstate_detect_period=60
++zpsstate_restart=0
+\ No newline at end of file
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_4Gb/fs/normal/rootfs/etc_ro/default/default_parameter_sys b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_4Gb/fs/normal/rootfs/etc_ro/default/default_parameter_sys
+index 57c1ad7..014d309 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_4Gb/fs/normal/rootfs/etc_ro/default/default_parameter_sys
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_4Gb/fs/normal/rootfs/etc_ro/default/default_parameter_sys
+@@ -439,7 +439,6 @@
+ NGECALL_FORTEST=0
+ CUSTOMER_FLAG=0
+ #for volte end
+-DEBUG_INFO_DISABLE=0
+ DEBUG_INFO_FILE_PATH=/mnt/userdata
+ DEBUG_INFO_FILE_NUM=2
+ DEBUG_INFO_FILE_TOTAL_SIZE=1
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_4Gb/fs/normal/rootfs/etc_ro/default/default_parameter_user b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_4Gb/fs/normal/rootfs/etc_ro/default/default_parameter_user
+index dc03706..7147993 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_4Gb/fs/normal/rootfs/etc_ro/default/default_parameter_user
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_4Gb/fs/normal/rootfs/etc_ro/default/default_parameter_user
+@@ -78,6 +78,10 @@
+ br_ipchange_flag=
+ br_node=usblan0+zvnet0
+ br_node_cap=zvnet0
++br_node_num=
++br_node0=
++br_node1=
++br_node2=
+ clat_fake_subnet=192.0.168.0
+ clat_frag_collect_timeout=300
+ clat_local_mapping_timeout=300
+@@ -490,6 +494,9 @@
+ gw_in_cap=0
+ #yes-on no-off
+ cc_at_debug=no
+-xlat_enable=0
++xlat_enable=1
+ telog_path_cap=
+ telog_path=
++zpsstate_detect=1
++zpsstate_detect_period=60
++zpsstate_restart=0
+\ No newline at end of file
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/init.d/rcS b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/init.d/rcS
+index e7959fe..0cb2386 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/init.d/rcS
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/init.d/rcS
+@@ -35,5 +35,6 @@
+
+ . /etc/rc.local
+
++sh /etc/lynq_monitor.sh &
+ exit 0
+
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/init.d/zcatlog_config.sh b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/init.d/zcatlog_config.sh
+index 5c6648f..0d099dd 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/init.d/zcatlog_config.sh
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/init.d/zcatlog_config.sh
+@@ -1,5 +1,31 @@
+ #!/bin/sh
+
++#jb.qi add for uci check start
++check_copy_file() {
++ if [ $# -ne 2 ];then
++ return
++ fi
++
++ diff $1 $2 > /dev/null
++ if [ $? -ne 0 ]; then
++ echo "cp $1 $2" > /dev/kmsg
++ cp $1 $2
++ fi
++}
++
++check_uci()
++{
++ uci get lynq_uci.lynq_ril > /dev/null
++ if [ $? -ne 0 ]; then
++ echo "$TAG: lynq_uci config cant get" > /dev/kmsg
++ cp /etc/config/lynq_uci /mnt/userdata/config/lynq_uci
++ fi
++}
++mkdir /mnt/userdata/config
++check_uci
++check_copy_file /etc/config/lynq_uci_ro /mnt/userdata/config/lynq_uci_ro
++
++#jb.qi add for uci check end
+ ramdump_mode=`nv get ramdump_mode`
+
+ if [ -e /proc/sys/ramdump_ap/ramdump_start_addr ]; then
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/lynq_monitor.sh b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/lynq_monitor.sh
+new file mode 100755
+index 0000000..72e61c7
+--- /dev/null
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/lynq_monitor.sh
+@@ -0,0 +1,60 @@
++#!/bin/sh
++while true
++do
++ sleep 30
++ ps -ef|grep lynq-sdk-ready |grep -v "grep" > /dev/null
++ if [ $? -ne 0 ]; then
++ echo "lynq-sdk-ready no exist" > /dev/kmsg
++ sh /etc/init.d/lynq-sdk-ready.sh start
++ else
++ ps -A -ostat,pid,comm |grep lynq-sdk-ready| grep Z > /dev/null
++ if [ $? -eq 0 ]; then
++ echo "lynq-sdk-ready state is Z" > /dev/kmsg
++ pid=$(ps -A -ostat,pid,comm |grep lynq-sdk-ready|grep Z|awk '{print $2}')
++ kill -9 $pid
++ sh /etc/init.d/lynq-sdk-ready.sh start
++ fi
++ fi
++
++ ps -ef|grep lynq-atcid |grep -v "grep" > /dev/null
++ if [ $? -ne 0 ]; then
++ echo "lynq-atcid no exist" > /dev/kmsg
++ sh /etc/init.d/lynq-atcid.sh start
++ else
++ ps -A -ostat,pid,comm |grep lynq-atcid| grep Z > /dev/null
++ if [ $? -eq 0 ]; then
++ echo "lynq-atcid state is Z" > /dev/kmsg
++ pid=$(ps -A -ostat,pid,comm |grep lynq-atcid|grep Z|awk '{print $2}')
++ kill -9 $pid
++ sh /etc/init.d/lynq-atcid.sh start
++ fi
++ fi
++
++ ps -ef|grep lynq-ril-service |grep -v "grep" > /dev/null
++ if [ $? -ne 0 ]; then
++ echo "lynq-ril-service no exist" > /dev/kmsg
++ sh /etc/init.d/lynq-ril-service.sh start
++ else
++ ps -A -ostat,pid,comm |grep lynq-ril-service| grep Z > /dev/null
++ if [ $? -eq 0 ]; then
++ echo "lynq-ril-service state is Z" > /dev/kmsg
++ pid=$(ps -A -ostat,pid,comm |grep lynq-ril-service|grep Z|awk '{print $2}')
++ kill -9 $pid
++ sh /etc/init.d/lynq-ril-service.sh start
++ fi
++ fi
++
++ ps -ef|grep autosuspend |grep -v "grep" > /dev/null
++ if [ $? -ne 0 ]; then
++ echo "lynq-autosuspend no exist" > /dev/kmsg
++ sh /etc/init.d/lynq-autosuspend.sh start
++ else
++ ps -A -ostat,pid,comm |grep autosuspend| grep Z > /dev/null
++ if [ $? -eq 0 ]; then
++ echo "lynq-autosuspend state is Z" > /dev/kmsg
++ pid=$(ps -A -ostat,pid,comm |grep autosuspend|grep Z|awk '{print $2}')
++ kill -9 $pid
++ sh /etc/init.d/lynq-autosuspend.sh start
++ fi
++ fi
++done
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/profile b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/profile
+index d8cbfdf..ba1dfaf 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/profile
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc/profile
+@@ -1,2 +1,2 @@
+
+-PATH="/sbin:/bin:/usr/sbin:/usr/bin:/mnt/oem/bin"
++PATH="/sbin:/usr/sbin:/bin:/usr/bin"
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc_ro/default/default_parameter_sys b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc_ro/default/default_parameter_sys
+index da7ced4..d5b8bbf 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc_ro/default/default_parameter_sys
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc_ro/default/default_parameter_sys
+@@ -451,7 +451,6 @@
+ NGECALL_FORTEST=0
+ CUSTOMER_FLAG=0
+ #for volte end
+-DEBUG_INFO_DISABLE=0
+ DEBUG_INFO_FILE_PATH=/mnt/userdata
+ DEBUG_INFO_FILE_NUM=2
+ DEBUG_INFO_FILE_TOTAL_SIZE=1
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc_ro/default/default_parameter_user b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc_ro/default/default_parameter_user
+index d43a308..f082891 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc_ro/default/default_parameter_user
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/etc_ro/default/default_parameter_user
+@@ -78,6 +78,10 @@
+ br_ipchange_flag=
+ br_node=usblan0+zvnet0
+ br_node_cap=zvnet0
++br_node_num=
++br_node0=
++br_node1=
++br_node2=
+ clat_fake_subnet=192.0.168.0
+ clat_frag_collect_timeout=300
+ clat_local_mapping_timeout=300
+@@ -346,7 +350,7 @@
+ ACL_mode=0
+ AuthMode=WPA2PSK
+ Channel=0
+-wifi_acs_num=5
++wifi_acs_num=3
+ closeEnable=0
+ closeTime=
+ CountryCode=CN
+@@ -432,6 +436,26 @@
+ wifi_profile8=
+ wifi_profile9=
+ wifi_profile_num=0
++wifi_prof_ssid=
++wifi_prof_ssid1=
++wifi_prof_ssid2=
++wifi_prof_ssid3=
++wifi_prof_ssid4=
++wifi_prof_ssid5=
++wifi_prof_ssid6=
++wifi_prof_ssid7=
++wifi_prof_ssid8=
++wifi_prof_ssid9=
++wifi_prof_pw=
++wifi_prof_pw1=
++wifi_prof_pw2=
++wifi_prof_pw3=
++wifi_prof_pw4=
++wifi_prof_pw5=
++wifi_prof_pw6=
++wifi_prof_pw7=
++wifi_prof_pw8=
++wifi_prof_pw9=
+ wifi_root_dir=
+ wifi_sta_connection=0
+ wifi_wps_index=1
+@@ -465,7 +489,9 @@
+ wifi_11n_cap_5g=1
+ WirelessMode_5g=6
+ Channel_5g=0
++# zw.wang [wifi] If the 5G hotspot is enabled, the country code cannot be obtained by calling qser_wifi_ap_channel_get on 20240829 start
+ CountryCode_5g=CN
++# zw.wang [wifi] If the 5G hotspot is enabled, the country code cannot be obtained by calling qser_wifi_ap_channel_get on 20240829 end
+ MAX_Access_num_5g=32
+ m_MAX_Access_num_5g=0
+ ACL_mode_5g=0
+@@ -511,7 +537,7 @@
+ at_at_d=
+ at_ptsnum=
+ quick_dial=1
+-cap_port_name=/dev/ttyGS0
++cap_port_name=/dev/ttyGS0+/dev/ttyGS1
+ customIndCmdList=
+ defrt_cid=1
+ MaxRtrAdvInterval=1800
+@@ -519,7 +545,10 @@
+ gw_in_cap=0
+ #yes-on no-off
+ cc_at_debug=no
+-xlat_enable=0
++xlat_enable=1
+ ecallmode=2
+ telog_path_cap=
+ telog_path=
++zpsstate_detect=1
++zpsstate_detect_period=60
++zpsstate_restart=0
+\ No newline at end of file
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/sbin/fdisk_emmc.sh b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/sbin/fdisk_emmc.sh
+index 492f934..ad96881 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/sbin/fdisk_emmc.sh
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_ref/fs/normal/rootfs/sbin/fdisk_emmc.sh
+@@ -15,7 +15,7 @@
+ p
+ 1
+
+-+200M
+++256M
+ n
+ p
+ 2
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_systemd/fs/normal/rootfs/etc_ro/default/default_parameter_sys b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_systemd/fs/normal/rootfs/etc_ro/default/default_parameter_sys
+index 57c1ad7..014d309 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_systemd/fs/normal/rootfs/etc_ro/default/default_parameter_sys
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_systemd/fs/normal/rootfs/etc_ro/default/default_parameter_sys
+@@ -439,7 +439,6 @@
+ NGECALL_FORTEST=0
+ CUSTOMER_FLAG=0
+ #for volte end
+-DEBUG_INFO_DISABLE=0
+ DEBUG_INFO_FILE_PATH=/mnt/userdata
+ DEBUG_INFO_FILE_NUM=2
+ DEBUG_INFO_FILE_TOTAL_SIZE=1
+diff --git a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_systemd/fs/normal/rootfs/etc_ro/default/default_parameter_user b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_systemd/fs/normal/rootfs/etc_ro/default/default_parameter_user
+index 3fbb096..92191d4 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_systemd/fs/normal/rootfs/etc_ro/default/default_parameter_user
++++ b/esdk/layers/meta-zxic-custom/recipes-core/images/files/zx297520v3/vehicle_dc_systemd/fs/normal/rootfs/etc_ro/default/default_parameter_user
+@@ -78,6 +78,10 @@
+ br_ipchange_flag=
+ br_node=usblan0+zvnet0
+ br_node_cap=zvnet0
++br_node_num=
++br_node0=
++br_node1=
++br_node2=
+ clat_fake_subnet=192.0.168.0
+ clat_frag_collect_timeout=300
+ clat_local_mapping_timeout=300
+@@ -488,6 +492,6 @@
+ MaxRtrAdvInterval=1800
+ dhcps_in_cap=1
+ gw_in_cap=0
+-xlat_enable=0
++xlat_enable=1
+ telog_path_cap=
+ telog_path=
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/liblynq-qser-gnss/liblynq-qser-gnss.bb b/esdk/layers/meta-zxic-custom/recipes-lynq/liblynq-qser-gnss/liblynq-qser-gnss.bb
+index 2eb9488..dd600c2 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/liblynq-qser-gnss/liblynq-qser-gnss.bb
++++ b/esdk/layers/meta-zxic-custom/recipes-lynq/liblynq-qser-gnss/liblynq-qser-gnss.bb
+@@ -50,11 +50,11 @@
+ fi
+ if [ "${MOBILETEK_GNSS_UPDATE_ENABLE}" = "yes" ]; then
+ install -d ${D}/data/gnss_update
+- install -m 644 ${WORKONSRC}HD8122.YIKE.GN3.115200.0035.720e5.53ef0.GQALS.ANT.EPH.CFG.PPS13.240115R1.bin ${D}/data/gnss_update
+- install -m 644 ${WORKONSRC}HD8122.YIKE.GN3.115200.0037.dbd12.53ef0.GAQBS.B1C.ANT.EPH.CFG.PPS13.240416R1.bin ${D}/data/gnss_update
++ install -m 644 ${WORKONSRC}HD8122.YF.GN3.115200.10038.c8069.53ef0.231110R2.GALQS.PPS9.CFG.EPHSave.bin ${D}/data/gnss_update
++ install -m 644 ${WORKONSRC}HD8122.YIKE.GN3.115200.0041.a8fb4.53ef0.GAQBS.B1C.ANT.EPH.CFG.PPS13.240912R1.bin ${D}/data/gnss_update
+ install -m 644 ${WORKONSRC}agps.conf ${D}/data/gnss_update
+- ln -sf ./HD8122.YIKE.GN3.115200.0035.720e5.53ef0.GQALS.ANT.EPH.CFG.PPS13.240115R1.bin ${D}/data/gnss_update/HD.bin
+- ln -sf ./HD8122.YIKE.GN3.115200.0037.dbd12.53ef0.GAQBS.B1C.ANT.EPH.CFG.PPS13.240416R1.bin ${D}/data/gnss_update/HD_BD.bin
++ ln -sf ./HD8122.YF.GN3.115200.10038.c8069.53ef0.231110R2.GALQS.PPS9.CFG.EPHSave.bin ${D}/data/gnss_update/HD.bin
++ ln -sf ./HD8122.YIKE.GN3.115200.0041.a8fb4.53ef0.GAQBS.B1C.ANT.EPH.CFG.PPS13.240912R1.bin ${D}/data/gnss_update/HD_BD.bin
+ fi
+ }
+
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/LICENSE b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/LICENSE
+deleted file mode 100755
+index 1b15bd2..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/LICENSE
++++ /dev/null
+@@ -1,31 +0,0 @@
+-opyright Statement:
+-
+-This software/firmware and related documentation ("MobileTek Software") are
+-protected under relevant copyright laws. The information contained herein is
+-confidential and proprietary to MobileTek Inc. and/or its licensors. Without
+-the prior written permission of MobileTek inc. and/or its licensors, any
+-reproduction, modification, use or disclosure of MobileTek Software, and
+-information contained herein, in whole or in part, shall be strictly
+-prohibited.
+-
+-MobileTek Inc. (C) 2015. All rights reserved.
+-
+-BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+-THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MobileTek SOFTWARE")
+-RECEIVED FROM MobileTek AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+-ON AN "AS-IS" BASIS ONLY. MobileTek EXPRESSLY DISCLAIMS ANY AND ALL
+-WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+-NONINFRINGEMENT. NEITHER DOES MobileTek PROVIDE ANY WARRANTY WHATSOEVER WITH
+-RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+-INCORPORATED IN, OR SUPPLIED WITH THE MobileTek SOFTWARE, AND RECEIVER AGREES
+-TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+-RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+-OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MobileTek
+-SOFTWARE. MobileTek SHALL ALSO NOT BE RESPONSIBLE FOR ANY MobileTek SOFTWARE
+-RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+-STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MobileTek'S
+-ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MobileTek SOFTWARE
+-RELEASED HEREUNDER WILL BE, AT MobileTek'S OPTION, TO REVISE OR REPLACE THE
+-MobileTek SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+-CHARGE PAID BY RECEIVER TO MobileTek FOR SUCH MobileTek SOFTWARE AT ISSUE.
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend.c b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend.c
+deleted file mode 100755
+index ff653f6..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend.c
++++ /dev/null
+@@ -1,101 +0,0 @@
+-/*
+- * Copyright (C) 2012 The Android Open Source Project
+- *
+- * Licensed under the Apache License, Version 2.0 (the "License");
+- * you may not use this file except in compliance with the License.
+- * You may obtain a copy of the License at
+- *
+- * http://www.apache.org/licenses/LICENSE-2.0
+- *
+- * Unless required by applicable law or agreed to in writing, software
+- * distributed under the License is distributed on an "AS IS" BASIS,
+- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+- * See the License for the specific language governing permissions and
+- * limitations under the License.
+- */
+-
+-#define LOG_TAG "AUTOSUSPEND"
+-
+-#include <stdbool.h>
+-
+-#include <log/log.h>
+-#include <liblog/lynq_deflog.h>
+-
+-#include "autosuspend.h"
+-
+-#include "autosuspend_ops.h"
+-
+-static struct autosuspend_ops *autosuspend_ops;
+-static bool autosuspend_enabled;
+-static bool autosuspend_inited;
+-
+-static int autosuspend_init(void)
+-{
+- if (autosuspend_inited) {
+- return 0;
+- }
+-
+- autosuspend_ops = autosuspend_wakeup_count_init();
+- if (autosuspend_ops) {
+- goto out;
+- }
+-
+- if (!autosuspend_ops) {
+- ALOGI("failed to initialize autosuspend\n");
+- return -1;
+- }
+-
+-out:
+- autosuspend_inited = true;
+-
+- ALOGI("autosuspend initialized\n");
+- return 0;
+-}
+-
+-int autosuspend_enable(void)
+-{
+- int ret;
+-
+- ret = autosuspend_init();
+- if (ret) {
+- return ret;
+- }
+-
+- ALOGI("autosuspend_enable\n");
+-
+- if (autosuspend_enabled) {
+- return 0;
+- }
+-
+- ret = autosuspend_ops->enable();
+- if (ret) {
+- return ret;
+- }
+-
+- autosuspend_enabled = true;
+- return 0;
+-}
+-
+-int autosuspend_disable(void)
+-{
+- int ret;
+-
+- ret = autosuspend_init();
+- if (ret) {
+- return ret;
+- }
+-
+- ALOGI("autosuspend_disable\n");
+-
+- if (!autosuspend_enabled) {
+- return 0;
+- }
+-
+- ret = autosuspend_ops->disable();
+- if (ret) {
+- return ret;
+- }
+-
+- autosuspend_enabled = false;
+- return 0;
+-}
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend.h b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend.h
+deleted file mode 100755
+index 59188a8..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend.h
++++ /dev/null
+@@ -1,58 +0,0 @@
+-/*
+- * Copyright (C) 2012 The Android Open Source Project
+- *
+- * Licensed under the Apache License, Version 2.0 (the "License");
+- * you may not use this file except in compliance with the License.
+- * You may obtain a copy of the License at
+- *
+- * http://www.apache.org/licenses/LICENSE-2.0
+- *
+- * Unless required by applicable law or agreed to in writing, software
+- * distributed under the License is distributed on an "AS IS" BASIS,
+- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+- * See the License for the specific language governing permissions and
+- * limitations under the License.
+- */
+-
+-#ifndef _LIBSUSPEND_AUTOSUSPEND_H_
+-#define _LIBSUSPEND_AUTOSUSPEND_H_
+-
+-#include <sys/cdefs.h>
+-#include <stdbool.h>
+-
+-__BEGIN_DECLS
+-
+-/*
+- * autosuspend_enable
+- *
+- * Turn on autosuspend in the kernel, allowing it to enter suspend if no
+- * wakelocks/wakeup_sources are held.
+- *
+- *
+- *
+- * Returns 0 on success, -1 if autosuspend was not enabled.
+- */
+-int autosuspend_enable(void);
+-
+-/*
+- * autosuspend_disable
+- *
+- * Turn off autosuspend in the kernel, preventing suspend and synchronizing
+- * with any in-progress resume.
+- *
+- * Returns 0 on success, -1 if autosuspend was not disabled.
+- */
+-int autosuspend_disable(void);
+-
+-/*
+- * set_wakeup_callback
+- *
+- * Set a function to be called each time the device returns from suspend.
+- * success is true if the suspend was sucessful and false if the suspend
+- * aborted due to some reason.
+- */
+-void set_wakeup_callback(void (*func)(bool success));
+-
+-__END_DECLS
+-
+-#endif
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend.service b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend.service
+deleted file mode 100755
+index 3cbb46c..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend.service
++++ /dev/null
+@@ -1,10 +0,0 @@
+-[Unit]
+-Description=lynq-autosuspend-service
+-
+-[Service]
+-ExecStart=/usr/bin/autosuspend
+-Type=simple
+-
+-[Install]
+-WantedBy=multi-user.target
+-
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend_ops.h b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend_ops.h
+deleted file mode 100755
+index 698e25b..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend_ops.h
++++ /dev/null
+@@ -1,29 +0,0 @@
+-/*
+- * Copyright (C) 2012 The Android Open Source Project
+- *
+- * Licensed under the Apache License, Version 2.0 (the "License");
+- * you may not use this file except in compliance with the License.
+- * You may obtain a copy of the License at
+- *
+- * http://www.apache.org/licenses/LICENSE-2.0
+- *
+- * Unless required by applicable law or agreed to in writing, software
+- * distributed under the License is distributed on an "AS IS" BASIS,
+- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+- * See the License for the specific language governing permissions and
+- * limitations under the License.
+- */
+-
+-#ifndef _LIBSUSPEND_AUTOSUSPEND_OPS_H_
+-#define _LIBSUSPEND_AUTOSUSPEND_OPS_H_
+-
+-struct autosuspend_ops {
+- int (*enable)(void);
+- int (*disable)(void);
+-};
+-
+-struct autosuspend_ops *autosuspend_autosleep_init(void);
+-struct autosuspend_ops *autosuspend_earlysuspend_init(void);
+-struct autosuspend_ops *autosuspend_wakeup_count_init(void);
+-
+-#endif
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend_wakeup_count.c b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend_wakeup_count.c
+deleted file mode 100755
+index c7cc274..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/autosuspend_wakeup_count.c
++++ /dev/null
+@@ -1,765 +0,0 @@
+-/*
+- * Copyright (C) 2012 The Android Open Source Project
+- *
+- * Licensed under the Apache License, Version 2.0 (the "License");
+- * you may not use this file except in compliance with the License.
+- * You may obtain a copy of the License at
+- *
+- * http://www.apache.org/licenses/LICENSE-2.0
+- *
+- * Unless required by applicable law or agreed to in writing, software
+- * distributed under the License is distributed on an "AS IS" BASIS,
+- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+- * See the License for the specific language governing permissions and
+- * limitations under the License.
+- */
+-
+-#define LOG_TAG "AUTOSUSPEND"
+-//#define LOG_NDEBUG 0
+-
+-#include <errno.h>
+-#include <fcntl.h>
+-#include <pthread.h>
+-#include <semaphore.h>
+-#include <stddef.h>
+-#include <stdbool.h>
+-#include <string.h>
+-#include <sys/param.h>
+-#include <sys/stat.h>
+-#include <sys/types.h>
+-#include <sys/time.h>
+-#include <libsim/lynq_sim.h>
+-
+-#include <unistd.h>
+-#include <dlfcn.h>
+-//#include <cutils/properties.h>
+-#define USER_LOG_TAG "PMS"
+-#include <liblog/lynq_deflog.h>
+-#include <include/lynq_uci.h>
+-
+-#include <log/log.h>
+-#include <stdlib.h>
+-#include "autosuspend_ops.h"
+-#include <sc_mnet_whitelist.h>
+-#include <sc_at.h>
+-#define SYS_POWER_STATE "/sys/power/state"
+-
+-#define SYS_POWER_WAKEUP_COUNT "/sys/power/wakeup_count"
+-#define SYS_POWER_SPM_SUSPEND_CRTL "/sys/power/spm/suspend_ctrl"
+-
+-#define BASE_SLEEP_TIME 100000
+-#define POSSIBLE_MAX_SLEEP_TIME 60000000
+-#define LOG_UCI_MODULE "lynq_autosuspend"
+-#define LOG_UCI_FILE "lynq_uci"
+-
+-static int state_fd;
+-static int wakeup_count_fd;
+-static int suspend_ctrl_fd;
+-static pthread_t suspend_thread;
+-static sem_t suspend_lockout;
+-extern pthread_cond_t feedback_cond;
+-extern pthread_mutex_t feedback_mutex;
+-extern pthread_mutex_t time_info_mutex;
+-static const char *sleep_state = "mem";
+-#ifdef MOBILETEK_SUSPEND_CFG
+-static const char *reg_netsys[5] = {"reg_netsys_srcclkena_mask_b 0",
+- "reg_netsys_infra_req_mask_b 0",
+- "reg_netsys_apsrc_req_mask_b 0",
+- "reg_netsys_vrf18_req_mask_b 0",
+- "reg_netsys_ddr_en_mask_b 0"};
+-#endif
+-static void (*wakeup_func)(bool success) = NULL;
+-static int sleep_time = BASE_SLEEP_TIME;
+-static int possible_max_sleep_time = POSSIBLE_MAX_SLEEP_TIME;
+-
+-extern int adb_debug_mode;
+-
+-static long start_time; // 出错点:time_info_t 结构体两个成员都是long,因此这两个变量必须是long型,不能定义成int
+-static long end_time;
+-
+-
+-
+-# define TEMP_FAILURE_RETRY(expression) \
+- (__extension__ \
+- ({ long int __result; \
+- do __result = (long int) (expression); \
+- while (__result == -1L && errno == EINTR); \
+- __result; }))
+-
+-
+-pid_t pid = 0;
+-
+-enum {
+- PARTIAL_WAKE_LOCK = 1, // the cpu stays on, but the screen is off
+- FULL_WAKE_LOCK = 2 // the screen is also on
+-};
+-
+-// while you have a lock held, the device will stay on at least at the
+-// level you request.
+-
+-struct time_info_t
+-{
+- long sleep_start_time;
+- long wakeup_time;
+-};
+-
+-extern struct time_info_t time_info;
+-
+-struct timeval tv;
+-
+-#ifdef MOBILETEK_SUSPEND_CFG
+-void *dlHandle_wakelock;
+-void *dlHandle_log;
+-void *dlHandle_network;
+-static void* dlHandle_sim;
+-
+-int (*lynq_screen)(int num);
+-int (*lynq_sim_init)(int utoken);
+-int (*acquire_wake_lock)(int lock, const char* id);
+-int (*release_wake_lock)(const char* id);
+-int (*lynq_query_registration_state)(const char *type,int* regState,int* imsRegState,char * LAC,char * CID,int *
+-netType,int *radioTechFam,int *errorCode);
+-int (*lynq_network_init)(int utoken);
+-
+-void init_wakelock_func(void)
+-{
+- const char *lynqLibPath_WakeLock = "/usr/lib64/libpower.so";
+- const char *lynqLibPath_Log = "/lib64/liblynq-log.so";
+-
+- dlHandle_wakelock = dlopen(lynqLibPath_WakeLock, RTLD_NOW);
+- if (dlHandle_wakelock == NULL)
+- {
+- ALOGI("dlopen lynqLibPath_WakeLock failed: %s", dlerror());
+- exit(EXIT_FAILURE);
+- }
+- dlHandle_log = dlopen(lynqLibPath_Log, RTLD_NOW);
+- if (dlHandle_log == NULL)
+- {
+- ALOGI("dlopen dlHandle_log failed: %s", dlerror());
+- exit(EXIT_FAILURE);
+- }
+- acquire_wake_lock = (int(*)(int,const char*))dlsym(dlHandle_wakelock, "acquire_wake_lock");
+- if (acquire_wake_lock == NULL) {
+- ALOGI("acquire_wake_lock not defined or exported in %s", lynqLibPath_WakeLock);
+- exit(EXIT_FAILURE);
+- }
+- release_wake_lock = (int(*)( const char*))dlsym(dlHandle_wakelock, "release_wake_lock");
+- if (release_wake_lock == NULL) {
+- ALOGI("release_wake_lock not defined or exported in %s", lynqLibPath_WakeLock);
+- exit(EXIT_FAILURE);
+- }
+- dlerror(); // Clear any previous dlerror
+-
+- return;
+-}
+-
+- void init_sim_func()
+-{
+- int res;
+- const char *lynqLibPath_Sim = "/lib64/liblynq-sim.so";
+-
+- pid = getpid();
+- dlHandle_sim = dlopen(lynqLibPath_Sim, RTLD_NOW);
+- if (dlHandle_sim == NULL)
+- {
+- ALOGI("dlopen lynqLibPath_Sim failed: %s", dlerror());
+- exit(EXIT_FAILURE);
+- }
+-
+- lynq_screen = (int(*)(int))dlsym(dlHandle_sim, "lynq_screen");
+- if (lynq_screen == NULL) {
+- ALOGI("lynq_screen not defined or exported in %s", lynqLibPath_Sim);
+- exit(EXIT_FAILURE);
+- }
+-
+- lynq_sim_init = (int(*)(int utoken))dlsym(dlHandle_sim,"lynq_sim_init");
+- if (lynq_sim_init == NULL) {
+- ALOGI("lynq_sim_init not defined or exported in %s", lynqLibPath_Sim);
+- exit(EXIT_FAILURE);
+- }
+- dlerror(); // Clear any previous dlerror
+-
+- res = lynq_sim_init((int)pid);
+- if(res == 0)
+- {
+- ALOGI("Run lynq_sim_init\n");
+- }else{
+- ALOGI("lynq sim init error\n");
+- }
+- sleep(1);
+-
+- return;
+-}
+-
+-
+-void init_network_func()
+-{
+- int res;
+- const char *lynqLibPath_Network = "/lib64/liblynq-network.so";
+- dlHandle_network = dlopen(lynqLibPath_Network, RTLD_NOW);
+- if (dlHandle_network == NULL)
+- {
+- ALOGI("dlopen lynqLibPath_Network failed: %s", dlerror());
+- exit(EXIT_FAILURE);
+- }
+-
+- lynq_query_registration_state = (int(*)(const char*,int*,int*,char *,char *,int *,int *,int*))dlsym(
+-dlHandle_network, "lynq_query_registration_state");
+- if (lynq_query_registration_state == NULL) {
+- ALOGI("lynq_query_registration_state not defined or exported in %s", lynqLibPath_Network);
+- exit(EXIT_FAILURE);
+- }
+-
+- lynq_network_init = (int(*)(int))dlsym(dlHandle_network, "lynq_network_init");
+- if (lynq_network_init == NULL) {
+- ALOGI("lynq_network_init not defined or exported in %s", lynqLibPath_Network);
+- exit(EXIT_FAILURE);
+- }
+-
+- ALOGI("start lynq_network_init\n");
+- printf("start lynq_network_init\n");
+- res = lynq_network_init(2);
+- sleep(10);
+-
+- if(res == 0)
+- {
+- ALOGI("Run lynq_network_init\n");
+- printf("Run lynq_network_init\n");
+- }else{
+- ALOGI("lynq_network_init error\n");
+- printf("lynq_network_init error\n");
+- }
+-
+- dlerror(); // Clear any previous dlerror
+- return;
+-}
+-#endif
+-
+-#ifdef MOBILETEK_TARGET_PLATFORM_T106
+-int t106_set_lowpwr(int state)
+-{
+- int ret;
+- char rsp[128];
+- char cmdstr[32];
+- if(state == 0)
+- {
+- strcpy(cmdstr, "AT+ZLOWPWR=0\r\n");
+- }
+- else
+- {
+- strcpy(cmdstr, "AT+ZLOWPWR=1\r\n");
+- }
+- ret = sc_at_send(1,cmdstr,rsp,sizeof(rsp));
+- printf("AT+ZLOWPWR result:%d %s\n",ret,rsp);
+- return ret;
+-}
+-
+-int t106_set_blacklist(int blacklist_state)
+-{
+- int ret;
+- char rsp[128];
+- char cmdstr[128];
+- if(blacklist_state == 0)
+- {
+- strcpy(cmdstr, "AT+SHELL=echo \"+CREG:+CGREG:+CEREG:^MODE:\" > /sys/module/at_io/parameters/at_psm_filter\r\n");
+- }
+- else
+- {
+- strcpy(cmdstr, "AT+SHELL=echo \"\" > /sys/module/at_io/parameters/at_psm_filter\r\n");
+- }
+- ret = sc_at_send(1,cmdstr,rsp,sizeof(rsp));
+- printf("AT+SHELL=echo result:%d %s\n",ret,rsp);
+- return ret;
+-
+-}
+-int t106_set_whitelist(void)
+-{
+- char tmp[8];
+- int ret;
+- lynq_get_value(LOG_UCI_FILE, LOG_UCI_MODULE, "whitelist_state", tmp);
+- if(strlen(tmp) != 4)
+- {
+- RLOGD("the whitelist len is error\n");
+- return 0;
+- }
+- if(tmp[0] == '1')
+- {
+- ret = sc_mnet_whitelist_add(1);
+- if(ret)
+- {
+- RLOGD("sc_mnet_whitelist_add 1 fail\n");
+- return ret;
+- }
+- ret = sc_mnet_whitelist_add(5);
+- if(ret)
+- {
+- RLOGD("sc_mnet_whitelist_add 5 fail\n");
+- return ret;
+- }
+- }
+- if(tmp[1] == '1')
+- {
+- ret = sc_mnet_whitelist_add(2);
+- if(ret)
+- {
+- RLOGD("sc_mnet_whitelist_add 2 fail\n");
+- return ret;
+- }
+- }
+- if(tmp[2] == '1')
+- {
+- ret = sc_mnet_whitelist_add(3);
+- if(ret)
+- {
+- RLOGD("sc_mnet_whitelist_add 3 fail\n");
+- return ret;
+- }
+- }
+- if(tmp[3] == '1')
+- {
+- ret = sc_mnet_whitelist_add(4);
+- if(ret)
+- {
+- RLOGD("sc_mnet_whitelist_add 4 fail\n");
+- return ret;
+- }
+- }
+-
+- return 0;
+-
+-}
+-int t106_early_suspend(void)
+-{
+- int ret;
+-
+- RLOGD("t106_early_suspend start\n");
+- ret=lynq_sleep_status(0);
+- RLOGD("lynq_get_sleep_status ret=%d\n", ret);
+- ret = t106_set_lowpwr(1);
+- RLOGD("t106_set_lowpwr status ret=%d\n", ret);
+- system("zlog_nvctrl -m 1");
+- ret = t106_set_whitelist();
+- if(ret)
+- {
+- RLOGD("t106_set_whitelist ret=%d\n", ret);
+- return ret;
+- }
+- ret = t106_set_blacklist(0);
+- if(ret)
+- {
+- RLOGD("t106_set_blacklist ret=%d\n", ret);
+- return ret;
+- }
+- return 0;
+-}
+-
+-void t106_early_resume(void)
+-{
+- int ret;
+- RLOGD("t106_early_resume start\n");
+- ret = t106_set_blacklist(1);
+- if(ret)
+- {
+- RLOGD("t106_set_whitelist ret=%d\n", ret);
+- }
+- ret = sc_mnet_whitelist_clear();
+- if(ret)
+- {
+- RLOGD("sc_mnet_whitelist_clear ret=%d\n", ret);
+- }
+- system("zlog_nvctrl -m 0");
+- ret = t106_set_lowpwr(0);
+- RLOGD("t106_set_lowpwr status ret=%d\n", ret);
+- ret=lynq_sleep_status(1);
+- RLOGD("lynq_get_sleep_status ret=%d\n", ret);
+-
+- return NULL;
+-}
+-#endif
+-
+-#ifdef MOBILETEK_SUSPEND_CFG
+-int t800_early_suspend(char *wakeup_count, int wakeup_count_len)
+-{
+- char buf[80];
+- system("echo \"Sys standby mode\" >/dev/console");
+- // sleep(1);
+- system("echo 7 | emdlogger_ctrl");
+- // sleep(1);
+-
+- if (lynq_screen(0) != 0) //notify ril for screen off
+- {
+- ALOGI("lynq_screen off fail\n");
+- return -1;
+- }
+- system("echo mode 4 0 >/sys/devices/platform/10005000.pinctrl/mt_gpio");
+- system("echo out 4 1 >/sys/devices/platform/10005000.pinctrl/mt_gpio");
+- RLOGD("ring GPIO PASS\n");
+- system("hwclock -w");
+- RLOGD("TIME: sys to rtc\n");
+- lseek(wakeup_count_fd, 0, SEEK_SET);
+- system("echo \"autosuspend:Sys seek\" >/dev/console");
+- wakeup_count_len = TEMP_FAILURE_RETRY(read(wakeup_count_fd, wakeup_count,
+- 200));
+- ALOGE("%s: %d, write %s to wakeup_count\n", __func__, wakeup_count_len, wakeup_count);
+- if (wakeup_count_len < 0) {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGE("Error reading from %s: %s\n", SYS_POWER_WAKEUP_COUNT, buf);
+- wakeup_count_len = 0;
+- return -1;
+- }
+-
+- for(int i = 0;i < 5;i++) //notify spm (other core) to handle pre-sleep configuration
+- {
+- if(TEMP_FAILURE_RETRY(write(suspend_ctrl_fd,reg_netsys[i],strlen(reg_netsys[i]))) < 0)
+- {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGI("Error writing to %s: %s\n", SYS_POWER_SPM_SUSPEND_CRTL, buf);
+- return -1;
+- }
+- }
+- return 0;
+-}
+-
+-void t800_early_resume(bool success)
+-{
+- system("hwclock -s");
+- RLOGD("TIME: rtc to sys\n");
+- if (!success)
+- {
+-
+- system("mdlogctl start");
+-
+- system("echo 8 | emdlogger_ctrl");
+-
+- usleep(200000);
+- ALOGI("Log on with failure\n");
+- return ;
+- }
+-
+- if (lynq_screen(1) != 0) // notify ril for screen on
+- {
+- ALOGI("lynq_screen on fail\n");
+- }
+-
+- system("mdlogctl start");
+-
+- system("echo 8 | emdlogger_ctrl");
+- usleep(300000); //delay 2s for ril handling screen on,at least 70ms
+-
+- return NULL;
+-}
+-#endif
+-
+-
+-static int suspend_ctrl(char *wakeup_count,int wakeup_count_len)
+-{
+-
+-
+- char buf[80];
+- int ret = 0;
+-#ifdef MOBILETEK_SUSPEND_CFG
+- ret = t800_early_suspend(char *wakeup_count, wakeup_count_len);
+- if(ret != 0)
+- {
+- ALOGD("t800_early_suspend fail\n");
+- return -1;
+- }
+-#endif
+-
+-
+-#ifdef MOBILETEK_TARGET_PLATFORM_T106
+- ret = t106_early_suspend();
+- if(ret != 0)
+- {
+- ALOGD("t106_early_suspend fail\n");
+- return -1;
+- }
+-#endif
+-
+- system("echo \"autosuspend:Sys suspend\" >/dev/console");
+- if(TEMP_FAILURE_RETRY(write(state_fd, sleep_state, strlen(sleep_state))) < 0) //enter suspend procedures in kernel
+- {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGI("Error writing to %s: %s\n", SYS_POWER_STATE, buf);
+- return -1;
+- }
+-
+- return 0;
+-}
+-
+-
+-void wakeup_feedback(bool success)
+-{
+-
+- char buf[80];
+- long sleeptime = 0;
+-
+-#ifdef MOBILETEK_SUSPEND_CFG
+- t800_early_resume(bool success);
+-#endif
+-
+-
+-#ifdef MOBILETEK_TARGET_PLATFORM_T106
+- t106_early_resume();
+-#endif
+-
+- pthread_mutex_lock(&time_info_mutex);
+- memset(&tv,0,sizeof(struct timeval));
+- gettimeofday(&tv,NULL);
+- // time_info.wakeup_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+- end_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+- ALOGI("%s: wake up time: %ld ms\n", __func__,end_time);
+-
+- memset(&time_info,0,sizeof(struct time_info_t));
+-
+- time_info.sleep_start_time = start_time;
+- time_info.wakeup_time = end_time;
+- sleeptime = end_time -start_time;
+- RLOGD("sleep time is %ld ms\n", sleeptime);
+- pthread_mutex_unlock(&time_info_mutex);
+-
+- if (pthread_cond_broadcast(&feedback_cond) != 0) {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGI("Error broadcast cond: %s\n", buf);
+- }
+-
+- return ;
+-
+-}
+-
+-static void update_sleep_time(bool success) {
+- if (success) {
+- sleep_time = BASE_SLEEP_TIME;
+- return;
+- }
+- // double sleep time after each failure up to one minute
+- sleep_time = MIN(sleep_time * 2, possible_max_sleep_time);
+-}
+-
+-static void *suspend_thread_func(void *arg __attribute__((unused)))
+-{
+- char buf[80];
+- char wakeup_count[20];
+- int wakeup_count_len;
+- int ret;
+- bool success = true;
+-
+- while (1) {
+- update_sleep_time(success);
+- usleep(sleep_time);
+- success = false;
+-
+- ALOGI("%s: wait\n", __func__);
+- ret = sem_wait(&suspend_lockout);
+- if (ret < 0) {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGI("Error waiting on semaphore: %s\n", buf);
+- continue;
+- }
+-
+- ALOGV("%s: read wakeup_count\n", __func__);
+- lseek(wakeup_count_fd, 0, SEEK_SET);
+- wakeup_count_len = TEMP_FAILURE_RETRY(read(wakeup_count_fd, wakeup_count,
+- sizeof(wakeup_count)));
+- if (wakeup_count_len < 0) {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGE("Error reading from %s: %s\n", SYS_POWER_WAKEUP_COUNT, buf);
+- wakeup_count_len = 0;
+- continue;
+- }
+- if (!wakeup_count_len) {
+- ALOGE("Empty wakeup count\n");
+- continue;
+- }
+-
+- ALOGI("%s: start suspend_ctrl\n", __func__);
+- memset(&tv,0,sizeof(struct timeval));
+- // memset(&time_info,0 ,sizeof(struct time_info_t));
+- gettimeofday(&tv,NULL);
+-
+- start_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+- ALOGI("%s: suspend start time: %ld ms\n", __func__,start_time);
+- // time_info.sleep_start_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+-
+- ret = suspend_ctrl(wakeup_count,wakeup_count_len);
+-
+- if (ret >= 0) {
+- ALOGI("suspend_ctrl success.\n");
+- success = true;
+- }
+- else
+- {
+- ALOGI("suspend_ctrl false.\n");
+- success = false;
+- }
+-
+- void (*func)(bool success) = wakeup_func;
+- if (func != NULL) {
+- (*func)(success); //handling resume event for other libs /apps
+- }
+-
+- ALOGI("%s: release sem\n", __func__);
+- ret = sem_post(&suspend_lockout);
+- if (ret < 0) {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGI("Error releasing semaphore: %s\n", buf);
+- }
+-
+- if(adb_debug_mode == 1) // it's neccessary to wait for autosuspend_disable function calling in debug mode when finish resume procedure.
+- {
+- sleep(40);
+- }
+- else
+- {
+- ALOGI("%s: adb_debug unsupported\n", __func__);
+- }
+-
+- ALOGI("%s: END SLEEP\n", __func__);
+- }
+- return NULL;
+-}
+-
+-static int autosuspend_wakeup_count_enable(void)
+-{
+- char buf[80];
+- int ret;
+-
+- ALOGI("autosuspend_wakeup_count_enable\n");
+-
+- ret = sem_post(&suspend_lockout);
+-
+- if (ret < 0) {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGI("Error changing semaphore: %s\n", buf);
+- }
+-
+- ALOGI("autosuspend_wakeup_count_enable done\n");
+-
+- return ret;
+-}
+-
+-static int autosuspend_wakeup_count_disable(void)
+-{
+- char buf[80];
+- int ret;
+-
+- ALOGI("autosuspend_wakeup_count_disable\n");
+-
+- ret = sem_wait(&suspend_lockout);
+-
+- if (ret < 0) {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGI("Error changing semaphore: %s\n", buf);
+- }
+-
+- ALOGI("autosuspend_wakeup_count_disable done\n");
+-
+- return ret;
+-}
+-
+-void set_wakeup_callback(void (*func)(bool success))
+-{
+- if (wakeup_func != NULL) {
+- ALOGI("Duplicate wakeup callback applied, keeping original");
+- return;
+- }
+- wakeup_func = func;
+-}
+-
+-struct autosuspend_ops autosuspend_wakeup_count_ops = {
+- .enable = autosuspend_wakeup_count_enable,
+- .disable = autosuspend_wakeup_count_disable,
+-};
+-
+-struct autosuspend_ops *autosuspend_wakeup_count_init(void)
+-{
+- int ret;
+- char buf[80];
+- char timeout_str[100]="100000";
+- pid = getpid();
+- char cmdstr[32];
+- char rsp[128];
+- //if (property_get("sys.autosuspend.timeout", timeout_str, NULL))
+- {
+- possible_max_sleep_time = atoi(timeout_str);
+- ALOGI("autosuspend timeout is %d\n", possible_max_sleep_time);
+- }
+-
+- state_fd = TEMP_FAILURE_RETRY(open(SYS_POWER_STATE, O_RDWR));
+- if (state_fd < 0) {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGI("Error opening %s: %s\n", SYS_POWER_STATE, buf);
+- goto err_open_state;
+- }
+-
+- wakeup_count_fd = TEMP_FAILURE_RETRY(open(SYS_POWER_WAKEUP_COUNT, O_RDWR));
+- if (wakeup_count_fd < 0) {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGI("Error opening %s: %s\n", SYS_POWER_WAKEUP_COUNT, buf);
+- goto err_open_wakeup_count;
+- }
+-#ifdef MOBILETEK_SUSPEND_CFG
+- suspend_ctrl_fd = TEMP_FAILURE_RETRY(open(SYS_POWER_SPM_SUSPEND_CRTL, O_RDWR));
+- if (suspend_ctrl_fd < 0) {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGI("Error opening %s: %s\n", SYS_POWER_SPM_SUSPEND_CRTL, buf);
+- goto err_open_suspend_ctrl;
+- }
+-#endif
+- ret = sem_init(&suspend_lockout, 0, 0);
+- if (ret < 0) {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGI("Error creating semaphore: %s\n", buf);
+- goto err_sem_init;
+- }
+-#ifdef MOBILETEK_TARGET_PLATFORM_T106
+- if(sc_at_init(1)){
+- ALOGD("sc_at_init failed.\n");
+- return NULL;
+- }
+- else
+- {
+- strcpy(cmdstr, "AT+ZPOWSTAT=1\r\n");
+- printf("AUTOSUSPEND: cmd:%s\n",cmdstr);
+- ret = sc_at_send(1,cmdstr,rsp,sizeof(rsp));
+- printf("AUTOSUSPEND: sc_at_send result:%d %s\n",ret,rsp);
+-
+- }
+- if(sc_mnet_whitelist_init() != 0)
+- {
+- ALOGD("sc_mnet_whitelist_init failed.\n");
+- return NULL;
+- }
+-#endif
+- ret = lynq_sim_init((int)pid);
+- if(ret == 0)
+- {
+- ALOGD("Run lynq_sim_init\n");
+- }
+- else
+- {
+- return NULL;
+- }
+- ret = pthread_create(&suspend_thread, NULL, suspend_thread_func, NULL);
+- if (ret) {
+- strerror_r(ret, buf, sizeof(buf));
+- ALOGI("Error creating thread: %s\n", buf);
+- goto err_pthread_create;
+- }
+-
+- ALOGI("Selected wakeup count\n");
+- return &autosuspend_wakeup_count_ops;
+-
+-err_pthread_create:
+- sem_destroy(&suspend_lockout);
+-err_sem_init:
+- close(wakeup_count_fd);
+-err_open_wakeup_count:
+- close(state_fd);
+-#ifdef MOBILETEK_SUSPEND_CFG
+-err_open_suspend_ctrl:
+- close(suspend_ctrl_fd);
+-#endif
+-err_open_state:
+- return NULL;
+-}
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/lynq-autosuspend.sh b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/lynq-autosuspend.sh
+deleted file mode 100755
+index 8e96831..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/lynq-autosuspend.sh
++++ /dev/null
+@@ -1,39 +0,0 @@
+-#!/bin/sh
+-#
+-# Run the daemon
+-#
+-
+-DAEMON="lynq-autosuspend-service"
+-PIDFILE="/var/run/$DAEMON.pid"
+-EXEC="/usr/bin/autosuspend"
+-EXEC_ARGS=""
+-
+-
+-start() {
+- echo -n "Starting $DAEMON... "
+- start-stop-daemon --no-close -S -b -m -p $PIDFILE -x $EXEC -- $EXEC_ARGS
+- [ $? -eq 0 ] && echo "OK" || echo "ERROR"
+-}
+-
+-stop() {
+- echo -n "Stopping $DAEMON... "
+- start-stop-daemon -K -p $PIDFILE
+- [ $? -eq 0 ] && echo "OK" || echo "ERROR"
+-}
+-
+-restart() {
+- stop
+- start
+-}
+-
+-case "$1" in
+- start|stop|restart)
+- "$1"
+- ;;
+- *)
+- echo "Usage: $0 {start|stop|restart}"
+- exit 1
+-esac
+-
+-exit $?
+-
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/main.c b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/main.c
+deleted file mode 100755
+index f706c9f..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/main.c
++++ /dev/null
+@@ -1,494 +0,0 @@
+-/* //device/system/rild/rild.c
+-**
+-** Copyright 2006 The Android Open Source Project
+-**
+-** Licensed under the Apache License, Version 2.0 (the "License");
+-** you may not use this file except in compliance with the License.
+-** You may obtain a copy of the License at
+-**
+-** http://www.apache.org/licenses/LICENSE-2.0
+-**
+-** Unless required by applicable law or agreed to in writing, software
+-** distributed under the License is distributed on an "AS IS" BASIS,
+-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-** See the License for the specific language governing permissions and
+-** limitations under the License.
+-*/
+-
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <stdbool.h>
+-#include <dlfcn.h>
+-#include <string.h>
+-#include <pthread.h>
+-#include <stdint.h>
+-#include <unistd.h>
+-#include <fcntl.h>
+-#include <errno.h>
+-#include <log/log.h>
+-#include <liblog/lynq_deflog.h>
+-#include <include/lynq_uci.h>
+-#include <sys/socket.h>
+-#include <sys/un.h>
+-#include <signal.h>
+-
+-
+-#define LOG_UCI_MODULE "lynq_autosuspend"
+-#define LOG_UCI_FILE "lynq_uci"
+-
+-#define LOG_TAG "AUTOSUSPEND"
+-
+-#define USER_LOG_TAG "PMS"
+-
+-#define SOCK_PATH "/tmp/autosuspend.cmd.server" //不能在当前这个目录创建socket文件,否则报错找不到文件(可能是因为这是在共享文件夹下,不支持创建socket文件)
+-
+-#define SOCK_DATA_PATH "/tmp/autosuspend.data.server"
+-
+-// #define LYINFLOG(X...) lynq_log_global_output(LOG_INFO,X)
+-
+-#define TIME_OUT_TIME 30
+-
+-
+-#define MAX_LIB_ARGS 16
+-
+-int adb_debug_mode = 0;
+-
+-
+-pthread_cond_t feedback_cond = PTHREAD_COND_INITIALIZER;
+-pthread_mutex_t feedback_mutex = PTHREAD_MUTEX_INITIALIZER;
+-pthread_mutex_t time_info_mutex = PTHREAD_MUTEX_INITIALIZER;
+-
+-extern int autosuspend_enable(void);
+-extern int autosuspend_disable(void);
+-extern void init_wakelock_func(void);
+-extern void init_sim_func();
+-extern void init_network_func();
+-extern void set_wakeup_callback(void (*func)(bool success));
+-extern void wakeup_feedback(bool success);
+-extern int (*lynq_screen)(int num);
+-
+-struct time_info_t
+-{
+- long sleep_start_time;
+- long wakeup_time;
+-};
+-
+-struct time_info_t time_info;
+-
+-static void usage(const char *argv0) {
+- fprintf(stderr, "Usage: %s -l <possible_max_sleep_time> [-- <args for Autosuspend Service>]\n", argv0);
+- exit(EXIT_FAILURE);
+-}
+-
+-
+-
+-static int make_argv(char * args, char ** argv) {
+- // Note: reserve argv[0]
+- int count = 1;
+- char * tok;
+- char * s = args;
+-
+- while ((tok = strtok(s, " \0"))) {
+- argv[count] = tok;
+- s = NULL;
+- count++;
+- }
+- return count;
+-}
+-
+-static int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
+-{
+- int n;
+-
+- while((n = accept(fd, sa, salenptr)) < 0)
+- {
+- if((errno == ECONNABORTED) || (errno == EINTR))
+- continue;
+- else
+- {
+- ALOGI("accept error\n");
+- return -1;
+- }
+- }
+- return n;
+-}
+-
+-static int Bind(int fd, const struct sockaddr *sa, socklen_t salen)
+-{
+- if(bind(fd, sa, salen) < 0)
+- {
+- // ALOGI("bind error\n");
+- perror("bind error");
+- return -1;
+- }
+- return 0;
+-}
+-
+-
+-static int Socket(int family, int type, int protocol)
+-{
+- int n;
+-
+- if ( (n = socket(family, type, protocol)) < 0)
+- {
+- ALOGI("socket error\n");
+- return -1;
+- }
+- return n;
+-}
+-
+-static int Listen(int fd, int backlog)
+-{
+- if(listen(fd, backlog) < 0)
+- {
+- ALOGI("listen error\n");
+- return -1;
+- }
+- return 0;
+-}
+-
+-
+-static int listen_port(struct sockaddr_un *addr, char *sockpath)
+-{
+- int listenfd;
+- listenfd = Socket(AF_UNIX,SOCK_STREAM,0);
+- if(listenfd == -1)
+- return -1;
+- memset(addr, 0, sizeof(struct sockaddr_un));
+- addr->sun_family = AF_UNIX;
+- strcpy(addr->sun_path,sockpath);
+- // int opt = 1;
+- // if(setsockopt(listenfd, SOL_SOCKET,SO_REUSEADDR, (const void *)&opt, sizeof(opt)) == -1)
+- // {
+- // perror("setsockopt error");
+- // return -1;
+- // }
+-
+-// 以上方法对非网络的本地socket无效,应该用unlink函数避免Address already in use的错误
+-
+-
+- unlink(sockpath);
+- if(Bind(listenfd,(struct sockaddr *)addr,sizeof(*addr)) == -1)
+- return -1;
+-
+- if(Listen(listenfd,20) == -1)
+- return -1;
+-
+- return listenfd;
+-}
+-
+-static ssize_t Read(int fd, void *ptr, size_t nbytes)
+-{
+- ssize_t n;
+-
+- while((n = read(fd, ptr, nbytes)) == -1)
+- {
+- //printf("READ,%d\n",fd);
+- if (errno == EINTR)
+- {
+- ALOGI("read error eintr\n");
+- continue;
+- }
+- else if(errno == EAGAIN || errno == EWOULDBLOCK)
+- {
+- ALOGI("read time out\n");
+- return -1;
+- }
+- else
+- {
+- ALOGI("read error\n");
+- return -1;
+- }
+- }
+- //sleep(2);
+- //printf("READ1,%d\n", fd);
+- return n;
+-}
+-
+-static ssize_t Write(int fd, const void *ptr, size_t nbytes)
+-{
+- ssize_t n;
+-
+- while((n = write(fd, ptr, nbytes)) == -1)
+- {
+- if (errno == EINTR)
+- continue;
+- else if(errno == EPIPE)
+- {
+- ALOGI("write error epipe\n");
+- return -1;
+- }
+- else
+- return -1;
+- }
+- return n;
+-}
+-
+-static int Close(int fd)
+-{
+- if (close(fd) == -1)
+- {
+- ALOGI("close error\n");
+- return -1;
+- }
+- return 0;
+-}
+-
+-
+-void *deal_autosuspend(void *sockfd)
+-{
+- int commfd = *((int *)sockfd);
+- char buf[20];
+- char res[15];
+-
+- while(1)
+- {
+- memset(buf,0,sizeof(buf));
+- ALOGI("deal_autosuspend start to read.\n");
+- // 错误点:read函数在对端关闭后,也会直接返回0,不会阻塞,因此要判断是否返回0,返回0表示对端已经关闭,此时要跳出while循环不再监听
+- // 为什么对端会关闭?因为在客户端没有用nohup方式打开的情况下,系统睡眠后客户端进行会直接被杀死,对端会关闭,所以会导致read不阻塞,且总是返回0的现象
+- if(Read(commfd,buf,sizeof(buf)) <= 0)
+- {
+- ALOGI("service receive suspend_cmd fail or client is closed.\n");
+- Close(commfd);
+- break;
+- }
+- if(strcmp(buf,"enable") == 0)
+- {
+- if(autosuspend_enable() < 0)
+- {
+- ALOGI("autosuspend_enable fail.\n");
+- }
+- else
+- {
+- ALOGI("autosuspend_enable success.\n");
+- }
+- }
+- else if(strcmp(buf,"disable") == 0)
+- {
+- if(autosuspend_disable() < 0)
+- {
+- ALOGI("autosuspend_disable fail.\n");
+- }
+- else
+- {
+- ALOGI("autosuspend_disable success.\n");
+-
+- }
+- }
+-
+- else
+- {
+- ALOGI("Unknown cmd : %s\n",buf);
+- }
+-
+- }
+-
+-
+-
+-}
+-
+-#ifdef GSW_SUSPEND_CFG
+-/*jb.qi add for service send when DTR is low on 20221111 start */
+-void *dtr_wakeup()
+-{
+- FILE *fp;
+- int ret;
+- bool success = true;
+- char buf[30];
+- char dtr_buffer[25];
+- RLOGD("dtr_wakeup start\n");
+- while(1)
+- {
+- fp = popen("cat /sys/devices/platform/10005000.pinctrl/mt_gpio |grep 006:","r");
+- fgets(dtr_buffer, sizeof(dtr_buffer), fp);
+- if(dtr_buffer[7] == '0')
+- {
+- time_info.sleep_start_time = 123;
+- time_info.wakeup_time = 123;
+- if (pthread_cond_broadcast(&feedback_cond) != 0)
+- {
+- strerror_r(errno, buf, sizeof(buf));
+- ALOGI("Error broadcast cond: %s\n", buf);
+- }
+- RLOGD("dtr_wakeup success!\n");
+- sleep(3);
+- }
+- usleep(500);
+- pclose(fp);
+- }
+-}
+-/*jb.qi add for service send when DTR is low on 20221111 end */
+-#endif
+-
+-void *send_feedback(void *sockfd)
+-{
+- int commfd = *((int *)sockfd);
+- char buf[80];
+-
+- while (1)
+- {
+- memset(buf,0,sizeof(buf));
+- ALOGI("send_feedback thread wait to send.\n");
+- pthread_mutex_lock(&feedback_mutex);
+- pthread_cond_wait(&feedback_cond,&feedback_mutex);
+-
+- ALOGI("send_feedback thread is now sending the feedback to client.\n");
+- pthread_mutex_lock(&time_info_mutex);
+- if(Write(commfd,&time_info,sizeof(struct time_info_t)) <= 0)
+- {
+- ALOGI("service send wakeup_feedback struct fail.\n");
+- Close(commfd);
+- pthread_mutex_unlock(&time_info_mutex);
+- pthread_mutex_unlock(&feedback_mutex);
+-#ifdef GSW_SUSPEND_CFG
+- continue ;//jb.qi add for service send when DTR is low on 20221111
+-#endif
+-
+-#ifdef MOBILETEK_SUSPEND_CFG
+- break ;
+-#endif
+- }
+- pthread_mutex_unlock(&time_info_mutex);
+-
+- pthread_mutex_unlock(&feedback_mutex);
+-
+-
+-
+- }
+-
+-}
+-
+-
+-int main(int argc, char **argv) {
+-
+-
+- // int i = 0;
+- // RLOGD("**Autosuspend Service Daemon Started**");
+- // RLOGD("**Autosuspend Service param count=%d**", argc);
+- char tmp[20];
+-
+- int commfd, commfd_data, server_sock, server_data_sock,len, len_data;
+-
+- struct sockaddr_un server_sockaddr;
+- struct sockaddr_un server_data_sockaddr;
+- struct sockaddr_un client_sockaddr;
+-
+- len = sizeof(server_sockaddr);
+-
+-
+- pthread_t tid;
+-#ifdef GSW_SUSPEND_CFG
+- pthread_t tid_1;//jb.qi add for service send when DTR is low on 20221111
+-#endif
+-
+- LYLOGEINIT(USER_LOG_TAG);
+- LYLOGSET(LOG_DEBUG);
+- // LYLOGSET(LOG_ERROR);
+-
+- int auto_enable = 0;
+-
+- lynq_get_value(LOG_UCI_FILE, LOG_UCI_MODULE, "debug", tmp); // 即获取系统层面的环境变量
+- ALOGI("Autosuspend Service Daemon. debug %s\n",tmp);
+- adb_debug_mode=atoi(tmp);
+- lynq_get_value(LOG_UCI_FILE, LOG_UCI_MODULE, "auto_enable", tmp);
+- auto_enable=atoi(tmp);
+- ALOGI("Autosuspend Service Daemon. auto_enable %s\n",tmp);
+-#ifdef MOBILETEK_SUSPEND_CFG
+- init_wakelock_func();
+- init_sim_func();
+-#endif
+- signal(SIGPIPE,SIG_IGN); // 忽略SIGPIPE信号,防止由于客户端关闭,继续往客户端write,会导致服务端收到SIGPIPE信号而Broken pipe
+-
+-
+- // init_network_func();
+-
+- // if(pthread_cond_init(&feedback_cond,NULL) != 0)
+- // {
+- // strerror_r(errno, buf, sizeof(buf));
+- // ALOGI("Error creating cond: %s\n", buf);
+- // return -1;
+- // }
+-
+- set_wakeup_callback(wakeup_feedback);
+- // 注册回调函数
+-
+- if(auto_enable==0)
+- {
+- if(autosuspend_disable() < 0)
+- {
+- ALOGI("autosuspend_disable fail.\n");
+- }
+- else
+- {
+- ALOGI("autosuspend_disable success.\n");
+- }
+- }
+- if(auto_enable==1)
+- {
+- if(autosuspend_enable() < 0)
+- {
+- ALOGI("autosuspend_enable fail.\n");
+- }
+- else
+- {
+- ALOGI("autosuspend_enable success.\n");
+- }
+- }
+-
+-
+- server_sock = listen_port(&server_sockaddr,SOCK_PATH);
+- if(server_sock == -1)
+- return -1;
+-
+- server_data_sock = listen_port(&server_data_sockaddr,SOCK_DATA_PATH);
+- if(server_data_sock == -1)
+- return -1;
+-#ifdef GSW_SUSPEND_CFG
+- /*jb.qi add for service send when DTR is low on 20221111 start*/
+- pthread_create(&tid_1,NULL,dtr_wakeup,NULL);
+- pthread_detach(tid_1);
+- /*jb.qi add for service send when DTR is low on 20221111 end*/
+-#endif
+-
+- while (1)
+- {
+- ALOGI("service socket listening...\n");
+- commfd = Accept(server_sock,(struct sockaddr *)&client_sockaddr,&len);
+- if(commfd == -1)
+- {
+- return -1;
+- }
+- if(getpeername(commfd, (struct sockaddr *)&client_sockaddr, &len) == -1)
+- {
+- ALOGI("GETPEERNAME ERROR.\n");
+- // Close(server_sock);
+- Close(commfd);
+- continue;
+- }
+- else
+- {
+- ALOGI("Client socket filepath: %s\n", client_sockaddr.sun_path);
+- }
+-
+- commfd_data = Accept(server_data_sock,NULL,NULL);
+- if(commfd_data == -1)
+- {
+- return -1;
+- }
+- ALOGI("data channel connected.\n");
+-
+- pthread_create(&tid,NULL,deal_autosuspend,(void*)&commfd);//这里很容易错,最后一个参数要取地址,这是一个指针
+- pthread_detach(tid);
+-
+- pthread_create(&tid,NULL,send_feedback,(void*)&commfd_data);
+- pthread_detach(tid);
+-
+-
+- }
+-
+-
+-}
+-
+-DEFINE_LYNQ_LIB_LOG(LYNQ_AUTOSUSPEND)
+-
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/makefile b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/makefile
+deleted file mode 100755
+index ca263bf..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/files/makefile
++++ /dev/null
+@@ -1,71 +0,0 @@
+-SHELL = /bin/sh
+-RM = rm -f
+-
+-LOCAL_CFLAGS := -Wall \
+- -g -Os \
+- -flto \
+- -DRIL_SHLIB \
+- -DATCI_PARSE \
+- -DKEEP_ALIVE \
+- -D__LINUX_OS__ \
+- -DECALL_SUPPORT
+-
+-
+-
+-ifeq ($(strip $(TARGET_PLATFORM)), T106)
+-LOCAL_CFLAGS += -DHAVE_SYS_UIO_H -DRIL_TIME_CB
+-endif
+-
+-ifeq ($(strip $(TARGET_PLATFORM)), T106)
+- LOCAL_CFLAGS += -DMOBILETEK_TARGET_PLATFORM_T106
+-endif
+-
+-ifeq ($(strip $(MOBILETEK_SUSPEND_CFG)), GSW)
+- LOCAL_CFLAGS += -DGSW_SUSPEND_CFG
+-
+-endif
+-
+-ifeq ($(strip $(MOBILETEK_SUSPEND_CFG)), PLATFORM)
+- LOCAL_CFLAGS += -DMOBILETEK_SUSPEND_CFG
+-
+-endif
+-
+-
+-LOCAL_PATH = .
+-
+-LOCAL_C_INCLUDES = \
+- -I. -I$(ROOT)$(includedir)/liblog -I$(ROOT)$(includedir) \
+-
+-
+-
+-
+-LOCAL_LIBS := \
+- -L. \
+- -ldl \
+- -lpthread \
+- -llynq-log \
+- -llynq-uci \
+- -llog \
+- -lbsp \
+- -lsctel \
+- -latutils \
+- -latreg \
+- -llynq-sim \
+-
+-
+-SOURCES = $(wildcard *.c )
+-
+-EXECUTABLE = autosuspend
+-
+-OBJECTS=$(SOURCES:.c=.o)
+-all: $(EXECUTABLE)
+-
+-$(EXECUTABLE): $(OBJECTS)
+- $(CXX) $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+-
+-%.o : %.c
+- $(CC) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+-
+-.PHONY: clean
+-clean:
+- $(RM) $(OBJECTS) $(EXECUTABLE)
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/lynq-autosuspend.bb b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/lynq-autosuspend.bb
+index a3df67f..f4e38fc 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/lynq-autosuspend.bb
++++ b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-autosuspend/lynq-autosuspend.bb
+@@ -1,68 +1,48 @@
+ inherit externalsrc package systemd
+
+ DESCRIPTION = "autosuspend.service"
++LICENSE = "CLOSED"
+
+-LICENSE = "MobileTekProprietary"
+ LIC_FILES_CHKSUM = "file://${WORKDIR}/LICENSE;md5=44d8d2b6296ca24bcd4894bb7155bf27"
++DEPENDS += "${@bb.utils.contains('TARGET_PLATFORM', 'mt2735', 'audio-mixer-ctrl streamer1.0', '', d)} liblynq-log liblynq-uci libbsp libsctel libatutils libatreg liblynq-sim"
+
+-SRC_URI = "file://autosuspend.c file://LICENSE \
+- file://autosuspend.h \
+- file://autosuspend_ops.h \
+- file://autosuspend_wakeup_count.c \
+- file://main.c \
+- file://autosuspend.service \
+- file://lynq-autosuspend.sh \
+- file://makefile \
+-"
+-
++WORKONSRC = "${TOPDIR}/../src/lynq/framework/lynq-autosuspend"
++FILESEXTRAPATHS_prepend :="${TOPDIR}/../src/lynq/framework/:"
++SRC_URI = " \
++ file://lynq-autosuspend \
++ "
++SRC-DIR = "${S}/../lynq-autosuspend"
+ EXTRA_OEMAKE = "'TARGET_PLATFORM = ${TARGET_PLATFORM}'"
+
+ TARGET_CC_ARCH += "${LDFLAGS}"
+-
+-LOCAL_C_INCLUDES = "-I. "
+-
+-DEPENDS = "liblynq-log liblynq-uci"
+-DEPENDS += "${@bb.utils.contains('TARGET_PLATFORM', 'mt2735', 'audio-mixer-ctrl streamer1.0', '', d)} liblynq-log liblynq-uci libbsp libsctel libatutils libatreg liblynq-sim"
+-LOCAL_LIBS = "-L. -ldl -lstdc++ -lpthread -llog"
+-SOURCES = "$(wildcard *.c )"
+-
+-OBJECTS = "$(SOURCES:.c=.o)"
+-
+-EXECUTABLE = "autosuspend"
+-S = "${WORKDIR}"
+-TARGET_CC_ARCH += "${LDFLAGS}"
+ SYSTEMD_PACKAGES = "${PN}"
+ SYSTEMD_SERVICE_${PN} = "autosuspend.service"
+ FILES_${PN} += "${systemd_unitdir}/system/autosuspend.service"
++
+ #INHIBIT_PACKAGE_STRIP = "1"
+ do_compile () {
+
+ #${CXX} -Wall ${LOCAL_C_INCLUDES} autosuspend.c autosuspend_wakeup_count.c main.c ${LOCAL_LIBS} -o ${EXECUTABLE}
+ if test "${PACKAGE_ARCH}" = "cortexa7hf-vfp-vfpv4-neon" || test "${PACKAGE_ARCH}" = "cortexa7hf-neon-vfpv4"; then
+- oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -mhard-float"
++ oe_runmake all -C ${SRC-DIR} ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -mhard-float"
+ else
+- oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST}"
++ oe_runmake all -C ${SRC-DIR} ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST}"
+ fi
+ }
+
+ do_install() {
+ install -d ${D}${bindir}/
+- echo "Installing image PN ${PN}"
+- echo "Installing image systemd_unitdir ${systemd_unitdir}"
+- echo "Installing image D ${D}"
+- echo "Installing image B ${B}"
++ install -m 0755 ${SRC-DIR}/autosuspend ${D}${bindir}/
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/autosuspend.service ${D}${systemd_unitdir}/system
+- else
++ else
+ install -d ${D}${sysconfdir}/init.d
+- install -m 0755 ${S}/lynq-autosuspend.sh ${D}${sysconfdir}/init.d/
+- install -d ${D}${sysconfdir}/rcS.d
+- ln -s ../init.d/lynq-autosuspend.sh ${D}${sysconfdir}/rcS.d/S82lynq-autosuspend-service
++ install -m 0755 ${SRC-DIR}/lynq-autosuspend.sh ${D}${sysconfdir}/init.d/
++ install -d ${D}${sysconfdir}/rcS.d
++ ln -s ../init.d/lynq-autosuspend.sh ${D}${sysconfdir}/rcS.d/S82lynq-autosuspend-service
+ fi
+
+- install -m 0755 ${S}/autosuspend ${D}${bindir}/
+- install -d ${D}${includedir}
+ }
+
+
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/LICENSE b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/LICENSE
+deleted file mode 100755
+index 0489348..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/LICENSE
++++ /dev/null
+@@ -1,31 +0,0 @@
+-opyright Statement:
+-
+-This software/firmware and related documentation ("MobileTek Software") are
+-protected under relevant copyright laws. The information contained herein is
+-confidential and proprietary to MobileTek Inc. and/or its licensors. Without
+-the prior written permission of MobileTek inc. and/or its licensors, any
+-reproduction, modification, use or disclosure of MobileTek Software, and
+-information contained herein, in whole or in part, shall be strictly
+-prohibited.
+-
+-Mobiletek Inc. (C) 2015. All rights reserved.
+-
+-BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+-THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MobileTek SOFTWARE")
+-RECEIVED FROM MobileTek AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+-ON AN "AS-IS" BASIS ONLY. MobileTek EXPRESSLY DISCLAIMS ANY AND ALL
+-WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+-NONINFRINGEMENT. NEITHER DOES MobileTek PROVIDE ANY WARRANTY WHATSOEVER WITH
+-RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+-INCORPORATED IN, OR SUPPLIED WITH THE MobileTek SOFTWARE, AND RECEIVER AGREES
+-TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+-RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+-OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MobileTek
+-SOFTWARE. MobileTek SHALL ALSO NOT BE RESPONSIBLE FOR ANY MobileTek SOFTWARE
+-RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+-STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MobileTek'S
+-ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MobileTek SOFTWARE
+-RELEASED HEREUNDER WILL BE, AT MobileTek'S OPTION, TO REVISE OR REPLACE THE
+-MobileTek SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+-CHARGE PAID BY RECEIVER TO MobileTek FOR SUCH MobileTek SOFTWARE AT ISSUE.
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/lynq-fota-backup.cpp b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/lynq-fota-backup.cpp
+deleted file mode 100755
+index c2e7d1d..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/lynq-fota-backup.cpp
++++ /dev/null
+@@ -1,259 +0,0 @@
+-/*******************************************************
+-*
+-* @brief:
+-* @details: add fota A/B backup service
+-* @author: l.yang
+-* @date: 2023.8.29
+-* @version: V1.0
+-* @copyright:Copyright (c) MobileTek
+-*
+-*********************************************/
+-
+-
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <stdbool.h>
+-#include <dlfcn.h>
+-#include <string.h>
+-#include <pthread.h>
+-#include <stdint.h>
+-#include <unistd.h>
+-#include <fcntl.h>
+-#include <errno.h>
+-#include <liblog/lynq_deflog.h>
+-
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#define FOTA_REBOOT_FLAG "/mnt/userdata/.fota_reboot_flag"
+-#define FOTA_FLAG_FILE "/mnt/userdata/.back_up_flag"
+-#define FOTA_SYNC_FLAG 1
+-#define FOTA_CURRENT_SYS "/mnt/userdata/.fota_current_sys"
+-
+-#define USER_LOG_TAG "LYNQ_FOTA_BACKUP"
+-
+-extern int lynq_sync_system();
+-extern int lynq_fota_get_addr_value(char *tmp_value);
+-extern int lynq_fota_set_addr_value(char *value,int size);
+-extern int lynq_fota_nrestart(void);
+-extern int lynq_get_current_system();
+-
+-
+-#define REBOOT_DONE 1
+-
+-void set_upgrade_reboot_flag(void)
+-{
+- FILE *fp = NULL;
+- int reboot_flag = REBOOT_DONE;
+- fp = fopen(FOTA_REBOOT_FLAG,"w+");
+- if(fp == NULL)
+- {
+- LYERRLOG("Open reboot flag file failed\n");
+- return;
+- }
+-
+- fwrite(&reboot_flag,sizeof(int),1,fp);
+- fclose(fp);
+- system("sync");
+- return ;
+-}
+-
+-int check_need_sync()
+-{
+- int current_sys = 0;
+- int record_sys = 0;
+- int ret = 0;
+- char tmp_sys[8] = {0};
+- FILE *fp = NULL;
+-
+- //not fota
+- if(access(FOTA_FLAG_FILE, F_OK) == -1)
+- {
+- LYINFLOG("Fota flag file no exist\n");
+-
+- //file no exist,get current sys write to file
+- if(access(FOTA_CURRENT_SYS,F_OK) == -1)
+- {
+- LYINFLOG("Record current sys file no exist\n");
+-
+- fp = fopen(FOTA_CURRENT_SYS,"w");
+- if(fp == NULL)
+- {
+- LYERRLOG("creat record current file failed\n");
+- return -1;
+- }
+- current_sys = lynq_get_current_system();
+- if(current_sys < 0)
+- {
+- LYERRLOG("Get current system failed %d\n",current_sys);
+- fclose(fp);
+- return -1;
+- }
+- else
+- {
+-
+- LYINFLOG("Get current system success %d\n",current_sys);
+- fprintf(fp, "%d", current_sys);
+- fclose(fp);
+- system("sync");
+-
+- return 0;
+- }
+- }
+- else
+- {
+- current_sys = lynq_get_current_system();
+- if(current_sys < 0)
+- {
+- LYERRLOG("Get current system failed %d\n",current_sys);
+- return -1;
+- }
+-
+- LYINFLOG("Get current system success %d\n",current_sys);
+-
+- fp = fopen(FOTA_CURRENT_SYS,"r");
+- if(fp == NULL)
+- {
+- LYERRLOG("read file failed \n");
+- return -1;
+- }
+-
+- if(fgets(tmp_sys, sizeof(tmp_sys), fp) != NULL)
+- {
+- record_sys = atoi(tmp_sys);
+- }
+- else
+- {
+- LYERRLOG("tmp_sys is NULL");
+- fclose(fp);
+- return -1;
+- }
+-
+- if( record_sys == current_sys)
+- {
+- LYINFLOG("System not need sync \n");
+- fclose(fp);
+- return 0;
+- }
+- else
+- {
+- LYINFLOG("System need sync \n");
+- ret = lynq_sync_system();
+- if(ret < 0 )
+- {
+- LYERRLOG("A/B sync system failed \n");
+- fclose(fp);
+- return -1;
+- }
+- LYINFLOG("A/B sync system success,record current sys \n");
+- fclose(fp);
+- fp = fopen(FOTA_CURRENT_SYS,"w");
+- if(fp == NULL)
+- {
+- LYERRLOG("creat file failed \n");
+- return -1;
+- }
+-
+- fprintf(fp,"%d",current_sys);
+- fclose(fp);
+- system("sync");
+-
+- return 0;
+- }
+- }
+-
+-
+- }
+- else
+- {
+- fp = fopen(FOTA_CURRENT_SYS,"w");
+- if(fp == NULL)
+- {
+- LYERRLOG("Creat file failed \n");
+- return -1;
+- }
+- LYINFLOG("fota flag file exist,record current sys \n");
+- current_sys = lynq_get_current_system();
+- if(current_sys < 0)
+- {
+- LYERRLOG("Get current system failed %d\n",current_sys);
+- fclose(fp);
+- return -1;
+- }
+-
+- fprintf(fp,"%d",current_sys);
+- fclose(fp);
+- system("sync");
+- return 0;
+- }
+-
+-
+-}
+-
+-int main()
+-{
+- int ret = 0 ;
+- int sync_flag = 0;
+- char tmp_addr[128] = {0};
+- FILE *fp = NULL;
+-
+- check_need_sync();
+-
+- fp = fopen(FOTA_FLAG_FILE,"r");
+- if(fp == NULL)
+- {
+- LYERRLOG("No need fota sync\n");
+- return -1;
+-
+- }
+-
+- fread(&sync_flag,sizeof(int),1,fp);
+- fclose(fp);
+-
+- set_upgrade_reboot_flag();
+-
+- if(sync_flag == FOTA_SYNC_FLAG)
+- {
+- ret = lynq_sync_system();
+- if(ret != 0)
+- {
+- LYERRLOG("sync faild\n");
+- }
+- system("rm -rf /mnt/userdata/.back_up_flag");
+-
+- }
+- else if(sync_flag != FOTA_SYNC_FLAG)
+- {
+- ret = lynq_fota_get_addr_value(tmp_addr);
+- if(ret != 0)
+- {
+- LYERRLOG("Get addr failed\n");
+- return -1;
+- }
+- LYINFLOG("tmp_addr is %s\n",tmp_addr);
+- ret = lynq_fota_set_addr_value(tmp_addr,10);
+- if(ret != 0)
+- {
+- LYERRLOG("Set addr failed\n");
+- return -1;
+- }
+- ret = lynq_fota_nrestart();
+- if(ret != 0)
+- {
+- LYERRLOG("Upgrade failed\n");
+- return -1;
+- }
+-
+- }
+-
+- return 0;
+-
+-}
+-DEFINE_LYNQ_LIB_LOG(LYNQ_FOTA_BACKUP)
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/lynq-fota-backup.service b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/lynq-fota-backup.service
+deleted file mode 100755
+index 28851ff..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/lynq-fota-backup.service
++++ /dev/null
+@@ -1,10 +0,0 @@
+-[Unit]
+-Description=lynq-fota-backup-service
+-
+-[Service]
+-ExecStart=/usr/bin/lynq-fota-backup
+-Type=simple
+-
+-[Install]
+-WantedBy=multi-user.target
+-
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/lynq-fota-backup.sh b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/lynq-fota-backup.sh
+deleted file mode 100755
+index 53eb20f..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/lynq-fota-backup.sh
++++ /dev/null
+@@ -1,39 +0,0 @@
+-#!/bin/sh
+-#
+-# Run the daemon
+-#
+-
+-DAEMON="lynq-fota-backup-service"
+-PIDFILE="/var/run/$DAEMON.pid"
+-EXEC="/usr/bin/lynq-fota-backup"
+-EXEC_ARGS=""
+-
+-
+-start() {
+- echo -n "Starting $DAEMON... "
+- start-stop-daemon --no-close -S -b -m -p $PIDFILE -x $EXEC -- $EXEC_ARGS
+- [ $? -eq 0 ] && echo "OK" || echo "ERROR"
+-}
+-
+-stop() {
+- echo -n "Stopping $DAEMON... "
+- start-stop-daemon -K -p $PIDFILE
+- [ $? -eq 0 ] && echo "OK" || echo "ERROR"
+-}
+-
+-restart() {
+- stop
+- start
+-}
+-
+-case "$1" in
+- start|stop|restart)
+- "$1"
+- ;;
+- *)
+- echo "Usage: $0 {start|stop|restart}"
+- exit 1
+-esac
+-
+-exit $?
+-
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/makefile b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/makefile
+deleted file mode 100755
+index 0a349d3..0000000
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/files/makefile
++++ /dev/null
+@@ -1,57 +0,0 @@
+-SHELL = /bin/sh
+-RM = rm -f
+-
+-LOCAL_CFLAGS := -Wall \
+- -std=gnu++14 \
+- -g -Os \
+- -flto \
+- -fPIC \
+-
+-
+-
+-ifeq ($(strip $(TARGET_PLATFORM)), T106)
+-LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1 -DHAVE_ENDIAN_H -DHAVE_PTHREADS -DHAVE_SYS_UIO_H -DHAVE_POSIX_FILEMAP -DHAVE_STRLCPY -DHAVE_PRCTL -DHAVE_MEMSET16 -DHAVE_MEMSET32 -DANDROID_SMP=0
+-endif
+-
+-LOCAL_CFLAGS += -Werror=format-security
+-
+-$(warning ################# rock ROOT: $(ROOT),includedir:$(includedir),)
+-
+-LOCAL_PATH = .
+-
+-LOCAL_C_INCLUDES = \
+- -I. \
+- -I$(LOCAL_PATH)/include \
+- -I$(ROOT)$(includedir)/logger \
+- -I$(ROOT)$(includedir)/liblog \
+- -I$(ROOT)$(includedir)/glib-2.0 \
+- -I$(ROOT)$(libdir)/glib-2.0/include \
+- -I$(ROOT)$(includedir) \
+-
+-
+-
+-LOCAL_LIBS := \
+- -L. \
+- -ldl \
+- -lstdc++ \
+- -llynq-log \
+- -llynq-fota \
+-
+-SOURCES = lynq-fota-backup.cpp
+-
+-EXECUTABLE = lynq-fota-backup
+-
+-OBJECTS=$(SOURCES:.cpp=.o)
+-
+-all: $(EXECUTABLE)
+-$(EXECUTABLE): $(OBJECTS)
+- $(CXX) $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+-
+-%.o : %.cpp
+- $(CXX) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+-
+-.PHONY: clean
+-clean:
+- $(RM) $(OBJECTS) $(EXECUTABLE)
+- $(RM) $(OBJECTS_TOOL) $(EXECUTABLE)
+-
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/lynq-fota-backup.bb b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/lynq-fota-backup.bb
+index b89f7ab..89ed7f6 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/lynq-fota-backup.bb
++++ b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-fota-backup/lynq-fota-backup.bb
+@@ -2,31 +2,28 @@
+
+ DESCRIPTION = "lynq-fota-backup.service"
+
+-LICENSE = "MIT"
++LICENSE = "CLOSED"
+ ##License checksum file is always required
+ LIC_FILES_CHKSUM = "file://${WORKDIR}/LICENSE;md5=c794e8ff1acd3b7f156a6497e780dd54"
+
+-SRC_URI = "file://lynq-fota-backup.cpp \
+- file://lynq-fota-backup.sh \
+- file://makefile \
+- file://lynq-fota-backup.service \
+- file://LICENSE \
+-"
++WORKONSRC = "${TOPDIR}/../src/lynq/framework/lynq-fota-backup"
+
+-
++FILESEXTRAPATHS_prepend :="${TOPDIR}/../src/lynq/framework/:"
++SRC_URI = " \
++ file://lynq-fota-backup \
++ "
++SRC-DIR = "${S}/../lynq-fota-backup"
+ TARGET_CC_ARCH += "${LDFLAGS}"
+-
+-
+ DEPENDS += "liblynq-log liblynq-uci liblynq-qser-fota"
+-S = "${WORKDIR}"
++
+ #INHIBIT_PACKAGE_STRIP = "1"
+ do_compile () {
+
+
+ if test "${PACKAGE_ARCH}" = "cortexa7hf-vfp-vfpv4-neon" || test "${PACKAGE_ARCH}" = "cortexa7hf-neon-vfpv4"; then
+- oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -mhard-float"
++ oe_runmake all -C ${SRC-DIR} ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -mhard-float"
+ else
+- oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST}"
++ oe_runmake all -C ${SRC-DIR} ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST}"
+ fi
+ }
+ #INHIBIT_PACKAGE_STRIP = "1"
+@@ -34,21 +31,16 @@
+
+ do_install() {
+ install -d ${D}${bindir}/
+- echo "Installing image PN ${PN}"
+- echo "Installing image systemd_unitdir ${systemd_unitdir}"
+- echo "Installing image D ${D}"
+- echo "Installing image B ${B}"
++ install -m 0755 ${SRC-DIR}/lynq-fota-backup ${D}${bindir}/
+
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/lynq-fota-backup.service ${D}${systemd_unitdir}/system
+ else
+ install -d ${D}${sysconfdir}/init.d
+- install -m 0755 ${S}/lynq-fota-backup.sh ${D}${sysconfdir}/init.d/
++ install -m 0755 ${SRC-DIR}/lynq-fota-backup.sh ${D}${sysconfdir}/init.d/
+ install -d ${D}${sysconfdir}/rcS.d
+ ln -s ../init.d/lynq-fota-backup.sh ${D}${sysconfdir}/rcS.d/S82lynq-fota-backup-service
+ fi
+
+- install -m 0755 ${S}/lynq-fota-backup ${D}${bindir}/
+- install -d ${D}${includedir}
+ }
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-gnss-update/files/main.c b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-gnss-update/files/main.c
+index 6b9fddd..c7752c6 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-gnss-update/files/main.c
++++ b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-gnss-update/files/main.c
+@@ -203,6 +203,9 @@
+ }
+
+ /*go to boot-mode need change pin status*/
++ lynq_gpio_init(84,1,0,0);
++ lynq_gpio_value_set(84,1);
++ usleep(500000);//500ms
+ lynq_gpio_init(15,1,0,0);
+ lynq_gpio_value_set(15, 0);
+ usleep(100000);//100ms
+@@ -213,6 +216,7 @@
+ usleep(100000);//100ms
+ lynq_gpio_direction_set(15, 0);
+ lynq_gpio_pullsel_set(15, 0);
++ lynq_gpio_deinit(84);
+ lynq_gpio_deinit(15);
+ lynq_gpio_deinit(126);
+
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-qser-voice-demo/files/lynq-qser-voice-demo.cpp b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-qser-voice-demo/files/lynq-qser-voice-demo.cpp
+index 41c5c97..e7eebc3 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-qser-voice-demo/files/lynq-qser-voice-demo.cpp
++++ b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-qser-voice-demo/files/lynq-qser-voice-demo.cpp
+@@ -29,6 +29,8 @@
+ {7, "qser_voice_set_test_num"},
+ {8, "qser_voice_fast_ecall"},
+ #endif
++ {9, "qser_voice_set_audio_mode"},
++ {10, "qser_voice_get_audio_mode"},
+ {-1, NULL}
+ };
+
+@@ -51,6 +53,9 @@
+ int (*qser_voice_set_speech_volume)(const int volume);
+ int (*qser_voice_get_speech_volume)(int *volume);
+ int (*qser_voice_set_dtmf)(const char callnum);
++int (*qser_voice_set_audio_mode)(const int audio_mode);
++int (*qser_voice_get_audio_mode)(int* audio_mode);
++
+
+ #ifdef ECALL_SUPPORT
+ int (*qser_voice_set_test_num)(voice_client_handle_type* h_voice,E_QSER_VOICE_ECALL_SET_TYPE_T type, const char *test_num, int test_num_length);
+@@ -119,6 +124,7 @@
+ int ret = 0;
+ int voice_call_id = 0;
+ voice_client_handle_type h_voice = 0;
++ int audio_mode = 0;
+
+ const char *lynqLibPath_Call = "/lib/liblynq-qser-voice.so";
+ dlHandle_call = dlopen(lynqLibPath_Call, RTLD_NOW);
+@@ -230,7 +236,23 @@
+ printf("qser_voice_add_ecall_indhandler not defined or exported in %s\n", lynqLibPath_Call);
+ return -1;
+ }
+-#endif
++#endif
++
++ qser_voice_set_audio_mode = (int(*)(const int audio_mode))dlsym(dlHandle_call, "qser_voice_set_audio_mode");
++ if(qser_voice_set_audio_mode == NULL)
++ {
++ printf("qser_voice_set_audio_mode not defined or exported in %s\n", lynqLibPath_Call);
++ return -1;
++ }
++
++
++ qser_voice_get_audio_mode = (int(*)(int* audio_mode))dlsym(dlHandle_call, "qser_voice_get_audio_mode");
++ if(qser_voice_get_audio_mode == NULL)
++ {
++ printf("qser_voice_get_audio_mode not defined or exported in %s\n", lynqLibPath_Call);
++ return -1;
++ }
++
+
+ ret = qser_voice_call_client_init(&h_voice);
+ if(ret != 0 )
+@@ -349,8 +371,12 @@
+ case 7:
+ {
+ char PhoneNum[32] = {0};
+- printf("please input test phone number: \n");
+- scanf("%s", PhoneNum);
++ printf("please input test phone number(input null means \"\"): \n");
++ scanf("%s", PhoneNum);
++ if(0 == strcmp(PhoneNum, "null"))
++ {
++ PhoneNum[0]='\0';
++ }
+ ret = qser_voice_set_test_num(&h_voice, E_QSER_VOICE_ECALL_SET_NUMBER, PhoneNum, strlen(PhoneNum)+1);
+ printf("qser_voice_set_test_num ret = %d\n", ret);
+ break;
+@@ -378,6 +404,22 @@
+ break;
+ }
+ #endif
++ case 9:
++ {
++
++ printf("please input voice audio mode: 0 codec, 1 rtp\n");
++ scanf("%d", &audio_mode);
++ ret = qser_voice_set_audio_mode(audio_mode);
++ printf("qser_voice_set_audio_mode ret = %d, audio_mode is %d\n", ret, audio_mode);
++ break;
++ }
++ case 10:
++ {
++ ret = qser_voice_get_audio_mode(&audio_mode);
++ printf("qser_voice_get_audio_mode ret = %d, audio_mode is %d\n", ret, audio_mode);
++ break;
++ }
++
+ default:
+ print_help();
+ break;
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-vb-demo/files/lynq_vb_demo.c b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-vb-demo/files/lynq_vb_demo.c
+new file mode 100755
+index 0000000..fc94d2a
+--- /dev/null
++++ b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-vb-demo/files/lynq_vb_demo.c
+@@ -0,0 +1,770 @@
++#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"
++
++#define _USE_VOICE_BUFFER
++#include "voice_lib.h"
++#include <fcntl.h>
++#include <signal.h>
++#include <semaphore.h>
++#include <sys/types.h>
++#include <pthread.h>
++
++/*command max len*/
++#define VOICE_CMD_MAX_LEN 64
++
++#define EXIT_CMD_STOP "stop\n"
++#define EXIT_CMD_Q "q\n"
++#define EXIT_CMD_EXIT "exit\n"
++
++#define REQ_VOICE_BUFFER_TEST_START "voice_buffer_test_start"
++#define REQ_VOICE_BUFFER_TEST_STOP "voice_buffer_test_stop"
++#define REQ_VOICE_BUFFER_LOOP_TEST_START "voice_buffer_loop_test_start"
++#define REQ_VOICE_BUFFER_LOOP_TEST_STOP "voice_buffer_loop_test_stop"
++#define REQ_VOICE_BUFFER_RTP_TEST_START "voice_buffer_rtp_test_start"
++#define REQ_VOICE_BUFFER_RTP_TEST_STOP "voice_buffer_rtp_test_stop"
++
++
++
++#define VBUFFER_TX_FILE_NAME "/mnt/userdata/tx.pcm"
++#define VBUFFER_RX_FILE_NAME "/mnt/userdata/rx.pcm"
++#define VBUFFER_TX16_FILE_NAME "/mnt/userdata/tx16.pcm"
++#define VBUFFER_RX16_FILE_NAME "/mnt/userdata/rx16.pcm"
++
++
++
++#define VB_MAX_INT 0x7fffffff
++#define VB_MIN_INT 0
++#define VB_INT_OVERFLOW(x) if((x < VB_MIN_INT)||(x > VB_MAX_INT)) x = 0;
++
++#define RX_FILE_LEN_MAX 0x100000
++
++
++
++typedef int (vb_thread_proc)(void*);
++struct vbuf_info_t
++{
++ int fd;
++ pthread_t rx_test_thread;
++ pthread_t tx_test_thread;
++ pthread_t loop_test_thread;
++ int quit;
++ char *tx_buf;
++ char *rx_buf;
++ int buf_size;
++ char *tx_filename;
++ char *rx_filename;
++ FILE *tx_file;
++ FILE *rx_file;
++ int tx_filesize;
++ int rx_filesize;
++ int fs;
++};
++
++static struct vbuf_info_t vbuf_rec;
++
++static void printUsage(const char *Opt)
++{
++ printf("Usage: %s\n", Opt);
++
++ printf("voice_buffer_test_start value: 8000,16000\n");
++ printf("voice_buffer_test_stop no value input\n");
++ printf("voice_buffer_loop_test_start value: 8000,16000\n");
++ printf("voice_buffer_loop_test_stop no value input\n");
++ printf("\n");
++}
++
++static int vbuffer_start_flag = 0;
++static int tx_optcount = 0;
++static int rx_optcount = 0;
++static int first_rderr_flag = 0;
++static int first_wrerr_flag = 0;
++
++static int vb_close_fd_release_buf()
++{
++ int ret = voice_buffer_close(vbuf_rec.fd);
++ if(ret != 0)
++ {
++ printf("%s : vb close fail \n",__func__);
++ }
++ vbuf_rec.fd = -1;
++
++ if(vbuf_rec.rx_buf)
++ {
++ free(vbuf_rec.rx_buf);
++ vbuf_rec.rx_buf = NULL;
++ }
++
++ if(vbuf_rec.tx_buf)
++ {
++ free(vbuf_rec.tx_buf);
++ vbuf_rec.tx_buf = NULL;
++ }
++
++ vbuffer_start_flag = 0;
++ printf("close buf fd and release buf end\n");
++ return ret;
++}
++
++
++
++//whole rx path
++static int vb_rx_test_thread_func(void *arg)
++{
++ int ret;
++
++ char* buf = vbuf_rec.rx_buf;
++ int size = vbuf_rec.buf_size;
++ int bytes_read = 0;
++ int r_size;
++
++
++ printf( "%s: start size=%d! \n",__func__,size);
++ memset (buf,0, size);
++
++ while (!vbuf_rec.quit)
++ {
++ rx_optcount ++;
++ VB_INT_OVERFLOW(rx_optcount);
++ if((rx_optcount%1000) == 0){
++ printf("%s: rx_optcount=%d! \n",__func__,rx_optcount);
++
++ }
++ else if(rx_optcount == 1000000){
++ printf("%s: rx_optcount=%d! \n",__func__,rx_optcount);
++ rx_optcount = 0;
++
++ }
++
++ //read form ps
++ r_size = voice_buffer_read(vbuf_rec.fd, buf, size);
++ if(r_size <= 0)
++ {
++ first_rderr_flag++;
++ VB_INT_OVERFLOW(first_rderr_flag);
++ continue ;
++ }
++ else{
++ first_rderr_flag = 0;
++
++ }
++
++ if(vbuf_rec.rx_file != NULL)
++ {
++ r_size = fwrite(buf, 1,size, vbuf_rec.rx_file);
++
++ if (r_size != size) {
++ //printf("Error fwrite size not eq,r_size=%d,size=%d\n",r_size,size);
++ }
++ else{
++
++ bytes_read += size;
++ if(bytes_read >= vbuf_rec.rx_filesize){
++ fseek(vbuf_rec.rx_file, 0, SEEK_SET);
++ bytes_read = 0;
++ printf("fwrite over write maxsize(%d)!!!\n",vbuf_rec.rx_filesize);
++
++ }
++ }
++ }
++
++
++ }
++
++ return 0;
++}
++
++static int vb_tx_test_thread_func(void *arg)
++{
++ int ret;
++ int num_read;
++
++
++ char* buf = vbuf_rec.tx_buf;
++
++ int size = vbuf_rec.buf_size;
++ int w_size;
++
++ printf("%s: start size=%d! \n",__func__,size);
++
++
++ memset(buf, 0,size);
++ while (!vbuf_rec.quit)
++ {
++
++ if(vbuf_rec.tx_file != NULL)
++ {
++
++ num_read = fread(buf,1,size, vbuf_rec.tx_file);
++
++ if (num_read != size) {
++ //printf("Error fread size not eq,num_read=%d,size=%d\n",num_read,size);
++ }
++ if (num_read <= 0) {
++ printf("Error fread size not eq,num_read=%d,size=%d\n",num_read,size);
++ fseek(vbuf_rec.tx_file, 0, SEEK_SET);
++ }
++ }
++ tx_optcount ++;
++ VB_INT_OVERFLOW(tx_optcount);
++
++ w_size = voice_buffer_write(vbuf_rec.fd, buf, size);
++ if(w_size <= 0)
++ {
++ first_wrerr_flag++;
++
++ VB_INT_OVERFLOW(first_wrerr_flag);
++
++ continue;
++ }
++ else{
++ first_wrerr_flag = 0;
++
++ }
++
++ }
++ return 0;
++}
++
++
++static int vb_thread_create( const char *name,pthread_t *thread_t, vb_thread_proc *proc,
++ int stack_size, unsigned priority,void *arg )
++{
++ pthread_attr_t thread_attr;
++ int ret;
++ int default_size;
++
++ struct sched_param param;
++ int policy = SCHED_FIFO;
++
++ printf("%s: start! \n",__func__);
++
++ /* Init thread attributes */
++ pthread_attr_init(&thread_attr);
++ /* Create the thread. */
++
++ ret = pthread_create( thread_t, &thread_attr,proc, arg);
++ if (ret != 0)
++ {
++ printf("%s: pthread_create fail,ret=%d! \n",__func__,ret);
++
++ pthread_attr_destroy(&thread_attr);
++ return ret;
++ }
++
++ pthread_attr_getstacksize(&thread_attr, &default_size);
++ printf("%s: pthread_attr_getstacksize(%d)! \n",__func__,default_size);
++
++ pthread_attr_destroy(&thread_attr);
++
++ printf("%s: end \n",__func__);
++ return 0;
++}
++
++
++int voice_buffer_stream_test_stop(void);
++
++int voice_buffer_stream_test_start(int fs)
++{
++ int ret = 0;
++ int buf_size = 320;
++ tx_optcount = 0;
++ rx_optcount = 0;
++ int* buf_int;
++
++ int i;
++
++ if(vbuffer_start_flag == 1){
++ printf(" VB already start,return \n");
++
++ return 0;
++ }
++
++ vbuffer_start_flag = 1;
++
++
++
++ if((vbuf_rec.fd != -1)&&(vbuf_rec.fd != 0)){
++ printf(" VB fd already get, vbuf_rec.fd=%d return \n",vbuf_rec.fd);
++ }
++
++ if(fs == 8000){
++
++ buf_size = 320;
++ }
++ else if(fs == 16000){
++
++ buf_size = 640;
++ }
++ else
++ {
++ buf_size = 320;
++ }
++ printf("Starting vb stream fs=%d buf_size=%d \n",fs,buf_size);
++
++ printf("%s:open tx and rx file \n",__func__);
++ if(fs == 8000){
++
++ vbuf_rec.tx_filename = VBUFFER_TX_FILE_NAME;//"/cache/tx.pcm";
++ vbuf_rec.rx_filename = VBUFFER_RX_FILE_NAME;//"/cache/rx.pcm";
++
++ }
++ else if(fs == 16000){
++
++ vbuf_rec.tx_filename = VBUFFER_TX16_FILE_NAME;//"/cache/tx16.pcm";
++ vbuf_rec.rx_filename = VBUFFER_RX16_FILE_NAME;//"/cache/rx16.pcm";
++
++ }
++ else
++ {
++ vbuf_rec.tx_filename = VBUFFER_TX_FILE_NAME;//"/cache/tx.pcm";
++ vbuf_rec.rx_filename = VBUFFER_RX_FILE_NAME;//"/cache/rx.pcm";
++
++ }
++
++
++
++
++ vbuf_rec.tx_file = fopen(vbuf_rec.tx_filename , "rb");
++ if (!vbuf_rec.tx_file) {
++ printf("Unable to open file '%s'\n", vbuf_rec.tx_filename);
++ //return -1;
++ }
++
++
++ vbuf_rec.rx_file = fopen(vbuf_rec.rx_filename, "wb");
++ if (!vbuf_rec.rx_file) {
++ printf(stderr, "Unable to create file '%s'\n", vbuf_rec.rx_filename);
++ //fclose(vbuf_rec.tx_file);
++
++ //return -1;
++ }
++ vbuf_rec.rx_filesize = RX_FILE_LEN_MAX;
++ printf("%s : vbuf_rec.rx_filesize(%d) \n",__func__,vbuf_rec.rx_filesize);
++
++ vbuf_rec.rx_buf = (char*) malloc(buf_size);
++ if(!vbuf_rec.rx_buf) {
++ printf("%s : malloc buf fail,return \n",__func__);
++ goto err;
++ }
++ vbuf_rec.tx_buf = (char*) malloc(buf_size);
++ if(!vbuf_rec.tx_buf) {
++ free(vbuf_rec.rx_buf);
++ printf("%s : malloc buf fail,return \n",__func__);
++ vbuf_rec.rx_buf = NULL;
++ goto err;
++ }
++ vbuf_rec.buf_size = buf_size;
++
++ vbuf_rec.quit = 0;
++
++ printf("%s : vb open start \n",__func__);
++
++
++ vbuf_rec.fd = voice_buffer_open();
++ if(vbuf_rec.fd <= 0){
++ printf("%s : vb open fail fd=%d,return \n",__func__,vbuf_rec.fd);
++ ret = -1;
++ goto err;
++
++ }
++ printf("%s :voice_buffer_open end \n",__func__);
++
++ printf("%s :rx tx vb_thread_create start \n",__func__);
++ ret = vb_thread_create ("vb_playback_test",&vbuf_rec.rx_test_thread, vb_rx_test_thread_func,
++ 4*1024,35,NULL);
++ if (ret != 0)
++ {
++ printf("%s :rx vb_thread_create fail ret=%d,return \n",__func__,ret);
++ vbuf_rec.rx_test_thread = NULL;
++ goto err;
++ }
++
++ printf("%s :rx vb_thread_create end \n",__func__);
++
++ ret = vb_thread_create ( "vbuf_record_test", &vbuf_rec.tx_test_thread, vb_tx_test_thread_func,
++ 4*1024,35,NULL);
++ if (ret != 0)
++ {
++
++ printf("%s :tx vb_thread_create fail ret=%d,return \n",__func__,ret);
++ vbuf_rec.tx_test_thread = NULL;
++ goto err;
++ }
++ printf("%s :tx vb_thread_create end \n",__func__);
++
++ return 0;
++
++err:
++ voice_buffer_stream_test_stop();
++
++ return ret;
++}
++
++
++//Stop stream
++int voice_buffer_stream_test_stop(void)
++{
++ int ret = 0;
++ printf("%s:rx tx thread exit start \n",__func__);
++ if(vbuf_rec.quit == 1) {
++ printf("%s,already stop ,return\n",__func__);
++
++ }
++
++ vbuf_rec.quit = 1;
++ voice_buffer_stop(vbuf_rec.fd);
++ if (vbuf_rec.tx_test_thread)
++ {
++ pthread_join (vbuf_rec.tx_test_thread,NULL);
++ vbuf_rec.tx_test_thread = NULL;
++
++ }
++
++ if (vbuf_rec.rx_test_thread)
++ {
++ pthread_join (vbuf_rec.rx_test_thread,NULL);
++ vbuf_rec.rx_test_thread = NULL;
++ }
++
++ if(vbuf_rec.tx_file != NULL)
++ {
++ fclose(vbuf_rec.tx_file);
++ printf("%s : vb close ,close tx file \n",__func__);
++ vbuf_rec.tx_file = NULL;
++ }
++
++ if(vbuf_rec.rx_file != NULL)
++ {
++
++ fclose(vbuf_rec.rx_file);
++ printf("%s : vb close ,close rx file \n",__func__);
++ vbuf_rec.rx_file = NULL;
++
++ }
++
++ vb_close_fd_release_buf();
++ return 0;
++}
++
++
++static int vb_loop_test_thread_func(void *arg)
++{
++ int ret;
++
++ char* buf = vbuf_rec.rx_buf;
++ int size = vbuf_rec.buf_size;
++
++ //char* buf = vbuf_rec.tx_buf;
++
++ //int size = vbuf_rec.buf_size;
++ int w_size;
++ int r_size;
++
++
++ printf( "%s: start size=%d! \n",__func__,size);
++ memset (buf,0, size);
++
++ while (!vbuf_rec.quit)
++ {
++ rx_optcount ++;
++ VB_INT_OVERFLOW(rx_optcount);
++ if((rx_optcount%1000) == 0){
++ printf("%s: rx_optcount=%d! \n",__func__,rx_optcount);
++
++ }
++ else if(rx_optcount == 1000000){
++ printf("%s: rx_optcount=%d! \n",__func__,rx_optcount);
++ rx_optcount = 0;
++
++ }
++
++ //read form ps
++ r_size = voice_buffer_read(vbuf_rec.fd, vbuf_rec.rx_buf, size);
++ if(r_size <= 0)
++ {
++ first_rderr_flag++;
++ VB_INT_OVERFLOW(first_rderr_flag);
++ continue ;
++ }
++ else{
++ first_rderr_flag = 0;
++ }
++ memcpy(vbuf_rec.tx_buf,vbuf_rec.rx_buf,size);
++ w_size = voice_buffer_write(vbuf_rec.fd, vbuf_rec.tx_buf, size);
++ if(w_size <= 0)
++ {
++ first_wrerr_flag++;
++
++ VB_INT_OVERFLOW(first_wrerr_flag);
++
++ continue;
++ }
++ else{
++ first_wrerr_flag = 0;
++ }
++
++ }
++
++ return 0;
++}
++
++
++int voice_buffer_stream_loop_test_stop(void);
++
++int voice_buffer_stream_loop_test_start(int fs)
++{
++ int ret = -1;
++ int buf_size = 320;
++ tx_optcount = 0;
++ rx_optcount = 0;
++ int* buf_int;
++
++ int i;
++
++ if(vbuffer_start_flag == 1){
++ printf(" VB already start,return \n");
++
++ return 0;
++ }
++
++ if((vbuf_rec.fd != -1)&&(vbuf_rec.fd != 0)){
++ printf(" VB fd already get, vbuf_rec.fd=%d return \n",vbuf_rec.fd);
++ }
++
++ vbuffer_start_flag = 1;
++
++ if(fs == 8000){
++
++ buf_size = 320;
++ }
++ else if(fs == 16000){
++
++ buf_size = 640;
++ }
++ else
++ {
++ buf_size = 320;
++ }
++ printf("Starting vb stream fs=%d buf_size=%d \n",fs,buf_size);
++
++ vbuf_rec.rx_buf = (char*) malloc(buf_size);
++ if(!vbuf_rec.rx_buf) {
++ printf("%s : malloc buf fail,return \n",__func__);
++ goto err;
++ }
++ vbuf_rec.tx_buf = (char*) malloc(buf_size);
++ if(!vbuf_rec.tx_buf) {
++ printf("%s : malloc buf fail,return \n",__func__);
++ goto err;
++ }
++ vbuf_rec.buf_size = buf_size;
++
++ vbuf_rec.quit = 0;
++
++ printf("%s : vb open start \n",__func__);
++
++
++ vbuf_rec.fd = voice_buffer_open();
++ if(vbuf_rec.fd <= 0){
++ printf("%s : vb open fail fd=%d,return \n",__func__,vbuf_rec.fd);
++ goto err;
++
++ }
++ printf("%s :loop vb_thread_create start \n",__func__);
++ ret = vb_thread_create ("vb_playback_test",&vbuf_rec.loop_test_thread, vb_loop_test_thread_func,
++ 4*1024,35,NULL);
++ if (ret != 0)
++ {
++ printf("%s :rx vb_thread_create fail ret=%d,return \n",__func__,ret);
++ goto err;
++ }
++
++ printf("%s :rx vb_thread_create end \n",__func__);
++
++ return 0;
++
++err:
++ voice_buffer_stream_loop_test_stop();
++
++ return ret;
++}
++
++int voice_buffer_stream_loop_test_stop(void)
++{
++ int ret = 0;
++ printf("%s:loop thread exit start \n",__func__);
++ if(vbuf_rec.quit == 1) {
++ printf("%s,already stop ,return\n",__func__);
++
++ }
++
++ vbuf_rec.quit = 1;
++ voice_buffer_stop(vbuf_rec.fd);
++ if (vbuf_rec.loop_test_thread)
++ {
++ pthread_join (vbuf_rec.loop_test_thread,NULL);
++ vbuf_rec.tx_test_thread = NULL;
++
++ }
++
++ vb_close_fd_release_buf();
++ return 0;
++}
++
++int voice_buffer_rtp_test_start(int fs)
++{
++ // refer to voice_buffer_stream_test_start(fs);
++ return 0;
++}
++
++
++
++int voice_buffer_rtp_test_stop(void)
++{
++// refer to voice_buffer_stream_loop_test_stop();
++ return 0;
++
++}
++
++void voice_buffer_cmd_proc(char *cmdstr)
++{
++ int ret = 0;
++ char data[VOICE_CMD_MAX_LEN];
++ int cmdstr_len = strlen(cmdstr); //-strlen("\r")
++ int value = 0;
++ int *p_value = &value;
++
++ cmdstr[cmdstr_len] = '\0'; //+strlen("\0")
++
++ ret = sscanf(cmdstr, "%s", data);
++ if(1 != ret){
++ printf("data sscanf failed!(%d)\n", ret);
++ return;
++ }
++ if(0 == strncmp(data, REQ_VOICE_BUFFER_TEST_START, strlen(REQ_VOICE_BUFFER_TEST_START))){
++
++ ret = sscanf(cmdstr, "%*s %d", &value);
++ if(1 != ret){
++ printf("%s,value sscanf failed!(%d)\n",data, ret);
++ return;
++ }
++
++ printf("%s set value %d\n", data, value);
++ ret = voice_buffer_stream_test_start(value);
++
++ printf("%s return ret=%d\n", data, ret);
++
++ }
++ else if(0 == strncmp(data, REQ_VOICE_BUFFER_TEST_STOP, strlen(REQ_VOICE_BUFFER_TEST_STOP))){
++ ret = voice_buffer_stream_test_stop();
++ printf("%s return %d\n", data, ret);
++ }
++ else if(0 == strncmp(data, REQ_VOICE_BUFFER_LOOP_TEST_START, strlen(REQ_VOICE_BUFFER_LOOP_TEST_START))){
++
++ ret = sscanf(cmdstr, "%*s %d", &value);
++ if(1 != ret){
++ printf("%s,value sscanf failed!(%d)\n",data, ret);
++ return;
++ }
++
++ printf("%s set value %d\n", data, value);
++ ret = voice_buffer_stream_loop_test_start(value);
++
++ printf("%s return ret=%d\n", data, ret);
++
++ }
++ else if(0 == strncmp(data, REQ_VOICE_BUFFER_LOOP_TEST_STOP, strlen(REQ_VOICE_BUFFER_LOOP_TEST_STOP))){
++ printf("voice_buffer_stream_loop_test_stop \n");
++ ret = voice_buffer_stream_loop_test_stop();
++ printf("%s return %d\n", data, ret);
++ }
++ else if(0 == strncmp(data, REQ_VOICE_BUFFER_RTP_TEST_START, strlen(REQ_VOICE_BUFFER_RTP_TEST_START))){
++
++ ret = sscanf(cmdstr, "%*s %d", &value);
++ if(1 != ret){
++ printf("%s,value sscanf failed!(%d)\n",data, ret);
++ return;
++ }
++
++ printf("%s set value %d\n", data, value);
++ ret = voice_buffer_rtp_test_start(value);
++
++ printf("%s return ret=%d\n", data, ret);
++
++ }
++ else if(0 == strncmp(data, REQ_VOICE_BUFFER_RTP_TEST_STOP, strlen(REQ_VOICE_BUFFER_RTP_TEST_STOP))){
++ ret = voice_buffer_rtp_test_stop();
++ printf("%s return %d\n", data, ret);
++ }
++ else{
++ printf("Request unknow.\n");
++ printUsage(cmdstr);
++ }
++}
++
++void vb_buffer_stop_all()
++{
++ voice_buffer_stream_loop_test_stop();
++ voice_buffer_stream_test_stop();
++ voice_buffer_rtp_test_stop();
++}
++
++void signal_handle_func(int sig)
++{
++ printf("sig(%d) signal_handle_func exit ",sig);
++
++ vb_buffer_stop_all();
++ exit(0);
++}
++
++int main(int argc, char **argv)
++{
++ char cmdstr[VOICE_CMD_MAX_LEN];
++
++ signal(SIGINT, signal_handle_func);
++ signal(SIGQUIT, signal_handle_func);
++ signal(SIGTERM, signal_handle_func);
++ signal(SIGPIPE, signal_handle_func);
++
++ memset(&vbuf_rec,0,sizeof(vbuf_rec));
++#if 0
++ /*add by hq for faster start @20240906,begin*/
++ if(argc>1)
++ {
++ voice_buffer_cmd_proc(argv[1]);
++ }
++ /*add by hq for faster start @20240906,end*/
++ else
++ {
++#endif
++ while(1){
++ printf("Please input an voice_demo command:\n");
++ if(NULL != fgets(cmdstr, VOICE_CMD_MAX_LEN - 1, stdin)){
++ if(0 == strcmp(EXIT_CMD_STOP, cmdstr) ||
++ 0 == strcmp(EXIT_CMD_Q, cmdstr) ||
++ 0 == strcmp(EXIT_CMD_EXIT, cmdstr)){
++ vb_buffer_stop_all();
++ break;
++ }
++
++ printf("len:%d, cmdstr:%s\n", strlen(cmdstr), cmdstr);
++
++ if(1 >= strlen(cmdstr)){
++ continue;
++ }
++ voice_buffer_cmd_proc(cmdstr);
++ }
++ }
++// }
++
++ printf("voice_demo end\n");
++
++ return 0;
++}
++
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-vb-demo/files/makefile b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-vb-demo/files/makefile
+new file mode 100755
+index 0000000..6a6f960
+--- /dev/null
++++ b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-vb-demo/files/makefile
+@@ -0,0 +1,47 @@
++SHELL = /bin/sh
++RM = rm -f
++
++LOCAL_CFLAGS := -Wall \
++ -g -Os \
++ -flto \
++ -fpermissive \
++ -fPIC \
++
++ifeq ($(strip $(TARGET_PLATFORM)), T106)
++LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1 -DHAVE_ENDIAN_H -DHAVE_PTHREADS -DHAVE_SYS_UIO_H -DHAVE_POSIX_FILEMAP -DHAVE_STRLCPY -DHAVE_PRCTL -DHAVE_MEMSET16 -DHAVE_MEMSET32 -DANDROID_SMP=0
++endif
++
++LOCAL_CFLAGS += -Werror=implicit-function-declaration
++
++$(warning ################# rock ROOT: $(ROOT),includedir:$(includedir),)
++
++LOCAL_PATH = .
++
++LOCAL_C_INCLUDES = \
++ -I. \
++ -I$(ROOT)$(includedir)/ \
++
++
++
++LOCAL_LIBS := \
++ -L. \
++ -ldl \
++ -lpthread \
++ -lvoice \
++
++SOURCES = $(wildcard *.c)
++
++EXECUTABLE = lynq_vb_demo
++
++OBJECTS=$(SOURCES:.c=.o)
++all: $(EXECUTABLE)
++
++$(EXECUTABLE): $(OBJECTS)
++ $(CC) $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
++
++%.o : %.c
++ $(CC) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
++
++.PHONY: clean
++clean:
++ $(RM) $(OBJECTS) $(EXECUTABLE)
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-vb-demo/lynq-vb-demo.bb b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-vb-demo/lynq-vb-demo.bb
+new file mode 100755
+index 0000000..b01d3b0
+--- /dev/null
++++ b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-vb-demo/lynq-vb-demo.bb
+@@ -0,0 +1,29 @@
++#inherit externalsrc package
++
++DESCRIPTION = "lynq-vb-demo"
++LICENSE = "CLOSED"
++LIC_FILES_CHKSUM = "file://LICENSE;md5=b1e07e8d88e26263e71d3a9e2aa9a2ff"
++DEPENDS += "libvoice"
++SRC_URI = "file://lynq_vb_demo.c \
++ file://makefile \
++"
++
++SRC-DIR = "${S}/../lynq-vb-demo"
++FILES_${PN} += "${bindir}/"
++TARGET_CC_ARCH += "${LDFLAGS}"
++
++S = "${WORKDIR}"
++
++#INHIBIT_PACKAGE_STRIP = "1"
++do_compile () {
++ if test "${PACKAGE_ARCH}" = "cortexa7hf-vfp-vfpv4-neon" || test "${PACKAGE_ARCH}" = "cortexa7hf-neon-vfpv4"; then
++ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -mhard-float"
++ else
++ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST}"
++ fi
++}
++
++do_install() {
++ install -d ${D}${bindir}/
++ install -m 0755 ${S}/lynq_vb_demo ${D}${bindir}/
++}
+diff --git a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-wifi-demo/files/lynq-wifi-demo.cpp b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-wifi-demo/files/lynq-wifi-demo.cpp
+index 445f51f..2264f5b 100755
+--- a/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-wifi-demo/files/lynq-wifi-demo.cpp
++++ b/esdk/layers/meta-zxic-custom/recipes-lynq/lynq-wifi-demo/files/lynq-wifi-demo.cpp
+@@ -211,6 +211,10 @@
+ printf("wakelock create fail\n");
+ printf("wifi_lock_num=%d\n", wifi_lock_num);
+ }
++ if (type == LYNQ_WIFI_AP_INDEX_AP0)
++ qser_wifi_work_mode_set(LYNQ_WIFI_WORK_MODE_AP0); // Set 2.4G, and this function must be called after the qser_wifi_enable function
++ else
++ qser_wifi_work_mode_set(LYNQ_WIFI_WORK_MODE_AP1); // Set 5G, and this function must be called after the qser_wifi_enable function
+ qser_wifi_ap_start(type); // Set the ap mode of 2.4G/5G
+ qser_wifi_register_handle(lynq_wifi_event_handle_demo, NULL, (void *)&args);
+ ret = qser_wakelock_lock(wifi_lock_num);
+@@ -220,6 +224,8 @@
+ printf("ret=%d\n", ret);
+ }
+ signal(SIGINT, signalHandler);
++ signal(SIGHUP, signalHandler);
++ signal(SIGTERM, signalHandler);
+ while (1)
+ {
+ char cmdstr[128] = {0};
+@@ -277,6 +283,8 @@
+ printf("ret=%d\n", ret);
+ }
+ signal(SIGINT, signalHandler);
++ signal(SIGHUP, signalHandler);
++ signal(SIGTERM, signalHandler);
+ while (1)
+ {
+ printf("[lynq-wifi-demo]Enter the ssid and password as shown in the following example:ssid auth paris pw ||sta_pkt_get ||sta_param_get || sta_scan ||sta_stop\n");
+diff --git a/esdk/layers/meta-zxic-selinux/recipes-security/refpolicy/files/policy-mls/policy/modules/system/locallogin.te b/esdk/layers/meta-zxic-selinux/recipes-security/refpolicy/files/policy-mls/policy/modules/system/locallogin.te
+index 103c0ef..5e63bbf 100755
+--- a/esdk/layers/meta-zxic-selinux/recipes-security/refpolicy/files/policy-mls/policy/modules/system/locallogin.te
++++ b/esdk/layers/meta-zxic-selinux/recipes-security/refpolicy/files/policy-mls/policy/modules/system/locallogin.te
+@@ -55,6 +55,9 @@
+ allow local_login_t local_login_tmp_t:file manage_file_perms;
+ files_tmp_filetrans(local_login_t, local_login_tmp_t, { file dir })
+
++allow local_login_t unreserved_port_t:tcp_socket { name_connect };
++allow local_login_t unreserved_port_t:udp_socket { name_bind };
++
+ kernel_read_system_state(local_login_t)
+ kernel_read_kernel_sysctls(local_login_t)
+ kernel_search_key(local_login_t)
+diff --git a/esdk/layers/meta-zxic/recipes-app/at-ctl/at-ctl.bb b/esdk/layers/meta-zxic/recipes-app/at-ctl/at-ctl.bb
+index 12ea54b..b9dd751 100755
+--- a/esdk/layers/meta-zxic/recipes-app/at-ctl/at-ctl.bb
++++ b/esdk/layers/meta-zxic/recipes-app/at-ctl/at-ctl.bb
+@@ -1,5 +1,5 @@
+ DESCRIPTION = "at_ctl"
+-DEPENDS = "libnvram libsoftap libsofttimer libatutils sqlcipher libatext libmxml libtelsvr libsd-daemon"
++DEPENDS = "libdebug-info libnvram libsoftap libsofttimer libatutils sqlcipher libatext libmxml libtelsvr libsd-daemon"
+ SECTION = "app"
+ LICENSE = "zte"
+ PV = "1.0.0"
+@@ -14,6 +14,7 @@
+
+ DEPENDS += " \
+ ${@bb.utils.contains('DISTRO_FEATURES', 'volte', 'libvoice', '', d)} \
++ ${@bb.utils.contains('DISTRO_FEATURES', 'use_voice_buffer', 'libvoice', '', d)} \
+ "
+
+ #配置code路径信息。
+@@ -34,13 +35,16 @@
+ include ${BSPDIR}/sources/meta-zxic/conf/pub.inc
+ CFLAGS_append = "-I ${BSPDIR}/zxic_code/zxic_source/zxic_app_open/platform/at_ctl/src/phone/inc"
+ CFLAGS_append += "${ZXIC_EXTRA_CFLAGS}"
++LIBS_append += "${@bb.utils.contains('DISTRO_FEATURES', 'volte', '-lvoice', '', d)}"
++LIBS_append += "${@bb.utils.contains('DISTRO_FEATURES', 'use_voice_buffer', '-lvoice', '', d)}"
+ LDLIBS_EXT = "${@bb.utils.contains('DISTRO_FEATURES', 'volte', '-lvoice', '', d)}"
++LDLIBS_EXT += "${@bb.utils.contains('DISTRO_FEATURES', 'use_voice_buffer', '-lvoice', '', d)}"
+ #include at-ctl.inc
+
+ #inherit autotools pkgconfig systemd
+
+ do_compile() {
+- make -C ${S_SRC_PATH} LDLIBS_EXT=${LDLIBS_EXT}
++ make -C ${S_SRC_PATH} LDLIBS_EXT="${LDLIBS_EXT}"
+ }
+
+ do_install () {
+@@ -87,4 +91,4 @@
+ SYSTEMD_SERVICE_${PN} = "at_ctl.service"
+ SYSTEMD_AUTO_ENABLE_${PN} = "enable"
+
+-RDEPENDS_${PN} = " libnvram libsoftap libsofttimer libatutils sqlcipher libatext libmxml libvoice libsd-daemon"
++RDEPENDS_${PN} = " libdebug-info libnvram libsoftap libsofttimer libatutils sqlcipher libatext libmxml libvoice libsd-daemon"
+diff --git a/esdk/layers/meta-zxic/recipes-app/libatext/libatext.bb b/esdk/layers/meta-zxic/recipes-app/libatext/libatext.bb
+index 0f5dcee..77066ff 100755
+--- a/esdk/layers/meta-zxic/recipes-app/libatext/libatext.bb
++++ b/esdk/layers/meta-zxic/recipes-app/libatext/libatext.bb
+@@ -1,4 +1,5 @@
+ DESCRIPTION = "libatext"
++DEPENDS = "libvoice "
+ SECTION = "lib"
+ LICENSE = "zte"
+ PV = "1.0.0"
+@@ -14,6 +15,7 @@
+ DEPENDS = "libatutils libnvram"
+ DEPENDS += " \
+ ${@bb.utils.contains('DISTRO_FEATURES', 'volte', 'libvoice', '', d)} \
++ ${@bb.utils.contains('DISTRO_FEATURES', 'use_voice_buffer', 'libvoice', '', d)} \
+ "
+
+ S = "${WORKDIR}"
+@@ -23,10 +25,13 @@
+ CFLAGS_append = "-I ${BSPDIR}/zxic_code/zxic_source/zxic_app_open/platform/at_ctl/inc"
+ CFLAGS_append += "${ZXIC_EXTRA_CFLAGS}"
+ LIBS_append += "${@bb.utils.contains('DISTRO_FEATURES', 'volte', '-lvoice', '', d)}"
++LIBS_append += "${@bb.utils.contains('DISTRO_FEATURES', 'use_voice_buffer', '-lvoice', '', d)}"
++LDLIBS_EXT = "${@bb.utils.contains('DISTRO_FEATURES', 'volte', '-lvoice', '', d)}"
++LDLIBS_EXT += "${@bb.utils.contains('DISTRO_FEATURES', 'use_voice_buffer', '-lvoice', '', d)}"
+ #include atext.inc
+
+ do_compile () {
+- make -C libatext
++ make -C libatext LDLIBS_EXT="${LDLIBS_EXT}"
+ }
+
+ do_install () {
+diff --git a/esdk/layers/meta-zxic/recipes-app/libreference-ril/libreference-ril.bb b/esdk/layers/meta-zxic/recipes-app/libreference-ril/libreference-ril.bb
+index d5a5367..5b56ebf 100755
+--- a/esdk/layers/meta-zxic/recipes-app/libreference-ril/libreference-ril.bb
++++ b/esdk/layers/meta-zxic/recipes-app/libreference-ril/libreference-ril.bb
+@@ -18,7 +18,7 @@
+
+ #编译
+ do_compile () {
+- make -C ril/reference-ril
++ make -C ril/reference-ril CONFIG_USE_NEW_SIGNAL_STRENGTH=${CONFIG_USE_NEW_SIGNAL_STRENGTH}
+ }
+
+ #库和头文件的安装
+diff --git a/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/Makefile b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/Makefile
+new file mode 100755
+index 0000000..c4f4780
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/Makefile
+@@ -0,0 +1,126 @@
++# /*****************************************************************************
++#* °æÈ¨ËùÓÐ (C)2015, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
++#*
++#* ÎļþÃû³Æ: Makefile
++#* Îļþ±êʶ: Makefile
++#* ÄÚÈÝÕªÒª: Makefile of ZTE librarys
++#* ʹÓ÷½·¨: void
++#*
++#* ÐÞ¸ÄÈÕÆÚ °æ±¾ºÅ Ð޸ıê¼Ç ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ
++#* -----------------------------------------------------------------------------
++#* 2018/01/15 V1.0 Create chentianming ´´½¨
++#*
++# ******************************************************************************/
++
++#*******************************************************************************
++# include ZTE library makefile
++#*******************************************************************************
++include $(COMMON_MK)
++
++
++#*******************************************************************************
++# library
++#*******************************************************************************
++LIB_SHARED = libtinyalsa.so
++LIB_STATIC = libtinyalsa.a
++
++OBJS = mixer.o pcm.o audio_mixer_ctrl.o
++CFLAGS += -g
++LDFLAGS += -lpthread
++
++##############USER COMIZE END##################
++
++CFLAGS += -I$(zte_lib_path)/libtinyalsa/include
++CFLAGS += -I$(STAGEDIR)/include
++CFLAGS += -I$(APP_DIR)/include
++CFLAGS += -fPIC
++
++LDFLAGS_SHARED += -shared
++
++
++#*******************************************************************************
++# comp test app and
++#*******************************************************************************
++EXEC_tinyplay = tinyplay
++EXEC_tinycap = tinycap
++EXEC_tinymix = tinymix
++EXEC_tinypcminfo = tinyinfo
++EXEC_alsatest = alsatest
++
++#*******************************************************************************
++# objects
++#*******************************************************************************
++tinyplay_OBJECTS += mixer.o pcm.o tinyplay.o
++tinycap_OBJECTS += mixer.o pcm.o tinycap.o
++tinymix_OBJECTS += mixer.o pcm.o tinymix.o
++tinypcminfo_OBJECTS += mixer.o pcm.o tinypcminfo.o
++alsatest_OBJECTS += mixer.o pcm.o alsatest.o
++
++#########################for linux######################################
++
++ifeq ($(V3PHONE_TYPE), K318)
++ CFLAGS += -D_USE_7520V3_PHONE_TYPE_K318
++endif
++ifeq ($(V3PHONE_TYPE), C31F)
++ CFLAGS += -D_USE_7520V3_PHONE_TYPE_C31F
++endif
++ifeq ($(V3PHONE_TYPE), XRSD)
++ CFLAGS += -D_USE_7520V3_PHONE_TYPE_XRSD
++endif
++ifeq ($(V3PHONE_TYPE), FWP)
++ CFLAGS += -D_USE_7520V3_PHONE_TYPE_FWP
++endif
++ifeq ($(V3PHONE_TYPE), WTWD)
++ CFLAGS += -D_USE_7520V3_PHONE_TYPE_WTWD
++endif
++
++
++CFLAGS += -I./include/
++CFLAGS += -g -Werror=implicit-function-declaration
++#CFLAGS += -D_USE_CODEC_TI3100
++SHAREDFLAG := -shared -lc
++#LDLIBS += -L$(LIB_DIR)/libtinyalsa
++#LDLIBS += -ltinyalsa
++
++all: $(LIB_STATIC) $(LIB_SHARED) $(EXEC_tinyplay) $(EXEC_tinycap) $(EXEC_tinymix) $(EXEC_tinypcminfo)
++
++$(LIB_STATIC) : $(OBJS)
++ $(AR) rcs $(LIB_STATIC) $(OBJS)
++
++$(LIB_SHARED): $(OBJS)
++ $(CC) $(LDFLAGS) $(LDFLAGS_SHARED) -o $@ $^
++
++
++$(EXEC_tinyplay): $(tinyplay_OBJECTS)
++ $(CC) $(LDFLAGS) -o $@ $(tinyplay_OBJECTS) -Wl,--start-group $(LDLIBS) -Wl,--end-group
++$(EXEC_tinycap): $(tinycap_OBJECTS)
++ $(CC) $(LDFLAGS) -o $@ $(tinycap_OBJECTS) -Wl,--start-group $(LDLIBS) -Wl,--end-group
++$(EXEC_tinymix): $(tinymix_OBJECTS)
++ $(CC) $(LDFLAGS) -o $@ $(tinymix_OBJECTS) -Wl,--start-group $(LDLIBS) -Wl,--end-group
++$(EXEC_tinypcminfo): $(tinypcminfo_OBJECTS)
++ $(CC) $(LDFLAGS) -o $@ $(tinypcminfo_OBJECTS) -Wl,--start-group $(LDLIBS) -Wl,--end-group
++#$(EXEC_alsatest): $(alsatest_OBJECTS)
++# $(CC) $(LDFLAGS) -o $@ $(alsatest_OBJECTS) -Wl,--start-group $(LDLIBS) -Wl,--end-group
++
++clean:
++ rm -f $(tinyplay_OBJECTS) $(tinycap_OBJECTS) $(tinymix_OBJECTS) $(tinypcminfo_OBJECTS) $(lib_OBJECTS) $(LIB_SHARED) $(LIB_STATIC) $(EXEC_tinyplay) $(EXEC_tinycap) $(EXEC_tinymix) $(EXEC_tinypcminfo) $(EXEC_alsatest) *.elf *.gdb *.o core
++
++romfs:
++ $(ROMFSINST) $(LIB_SHARED) /lib/$(LIB_SHARED)
++ $(ROMFSINST) $(EXEC_tinyplay) /bin/$(EXEC_tinyplay)
++ $(ROMFSINST) $(EXEC_tinycap) /bin/$(EXEC_tinycap)
++ $(ROMFSINST) $(EXEC_tinymix) /bin/$(EXEC_tinymix)
++ # $(ROMFSINST) $(EXEC_tinypcminfo) /bin/$(EXEC_tinypcminfo)
++ cp -v $(EXEC_tinyplay) $(APP_DIR)/test_tools/
++ cp -v $(EXEC_tinycap) $(APP_DIR)/test_tools/
++ cp -v $(EXEC_tinymix) $(APP_DIR)/test_tools/
++ cp -v $(EXEC_tinypcminfo) $(APP_DIR)/test_tools/
++# $(ROMFSINST) $(EXEC_alsatest) /bin/$(EXEC_alsatest)
++
++
++# cp $(EXEC_tinyplay) $(EXEC_tinyplay).elf
++# cp $(EXEC_tinycap) $(EXEC_tinycap).elf
++
++# cp $(EXEC_tinymix) $(EXEC_tinymix).elf
++# cp $(EXEC_tinypcminfo) $(EXEC_tinypcminfo).elf
++# cp $(EXEC_alsatest) $(EXEC_alsatest).elf
+diff --git a/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/alsatest.c b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/alsatest.c
+new file mode 100755
+index 0000000..e599fff
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/alsatest.c
+@@ -0,0 +1,764 @@
++#include <stdio.h>
++#include <unistd.h>
++#include <string.h>
++//#include <stdlib.h>
++//#include "pthread.h"
++//#include "alsatest.h"
++//#include <stdbool.h>
++#include <fcntl.h>
++#include <signal.h>
++#include <tinyalsa/asoundlib.h>
++#include <sound/asound.h>
++#include <stdint.h>
++#include <stdbool.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <ctype.h>
++
++#define ID_RIFF 0x46464952
++#define ID_WAVE 0x45564157
++#define ID_FMT 0x20746d66
++#define ID_DATA 0x61746164
++
++#define FORMAT_PCM 1
++#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
++
++
++struct riff_wave_header {
++ uint32_t riff_id;
++ uint32_t riff_sz;
++ uint32_t wave_id;
++};
++
++struct chunk_header {
++ uint32_t id;
++ uint32_t sz;
++};
++
++struct chunk_fmt {
++ uint16_t audio_format;
++ uint16_t num_channels;
++ uint32_t sample_rate;
++ uint32_t byte_rate;
++ uint16_t block_align;
++ uint16_t bits_per_sample;
++};
++struct wav_header {
++ uint32_t riff_id;
++ uint32_t riff_sz;
++ uint32_t riff_fmt;
++ uint32_t fmt_id;
++ uint32_t fmt_sz;
++ uint16_t audio_format;
++ uint16_t num_channels;
++ uint32_t sample_rate;
++ uint32_t byte_rate;
++ uint16_t block_align;
++ uint16_t bits_per_sample;
++ uint32_t data_id;
++ uint32_t data_sz;
++};
++
++enum t_output_path{
++ T_OUTPUT_RECEIVER,
++ T_OUTPUT_SPEAKER,
++ T_OUTPUT_HEADSET,
++};
++
++enum t_input_path{
++ T_INPUT_MICLP,
++ T_INPUT_MICRP,
++};
++
++enum t_output_vol{
++ T_OUTPUT_VOL_MINUS_63_5DB = 0,
++ T_OUTPUT_VOL_MINUS_63DB = 1,
++ T_OUTPUT_VOL_MINUS_6DB = 115,
++ T_OUTPUT_VOL_MINUS_3DB = 121,
++ T_OUTPUT_VOL_MINUS_2DB = 123,
++ T_OUTPUT_VOL_MINUS_1DB = 125,
++ T_OUTPUT_VOL_0DB = 127,
++ T_OUTPUT_VOL_1DB = 129,
++ T_OUTPUT_VOL_2DB = 131,
++ T_OUTPUT_VOL_3DB = 133,
++ T_OUTPUT_VOL_6DB = 139,
++ T_OUTPUT_VOL_9DB = 145,
++ T_OUTPUT_VOL_12DB = 151,
++ T_OUTPUT_VOL_24DB = 175,
++};
++
++enum t_input_vol{
++ T_INPUT_VOL_MINUS_12DB = 0,
++ T_INPUT_VOL_MINUS_3DB = 18,
++ T_INPUT_VOL_MINUS_2DB = 20,
++ T_INPUT_VOL_MINUS_1DB = 22,
++ T_INPUT_VOL_0DB = 24,
++ T_INPUT_VOL_1DB = 26,
++ T_INPUT_VOL_2DB = 28,
++ T_INPUT_VOL_3DB = 30,
++ T_INPUT_VOL_20DB = 64,
++};
++
++struct audio_para_conf {
++ const char *control;
++ char *values[2];
++};
++
++static struct audio_para_conf common_out_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ {"Speaker Analog Playback Volume",{"127"}},
++ {"Speaker Driver Playback Switch",{"1"}},
++ {"DAC Left Input",{"Mono"}},
++ {"DAC Right Input",{"Mono"}},
++ {"Output Right From Right DAC",{"1"}},
++ {"Output Left From Left DAC",{"1"}},
++ {"HP Analog Playback Volume",{"127","127"}},
++ {"HP Driver Playback Switch",{"1","1"}}, //7dB
++
++};
++
++static struct audio_para_conf common_in_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ {"Mic PGA Capture Volume",{"40"}},
++ {"ADC Capture Switch",{"1"}},
++ {"ADC Fine Capture Volume",{"0"}},
++
++};
++
++static struct audio_para_conf hp_outpath_para_audio[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ
++ {"Speaker Switch",{"0"}},
++ {"HP Left Switch",{"1"}},
++ {"HP Right Switch",{"1"}},
++ {"HP Driver Playback Volume",{"0","0"}},
++};
++
++static struct audio_para_conf spk_outpath_para_audio[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀ
++ {"Speaker Switch",{"1"}},
++ {"Speaker Driver Playback Volume",{"2"}}, //18dB
++ {"HP Left Switch",{"0"}},
++ {"HP Right Switch",{"0"}},
++};
++
++static struct audio_para_conf mic1lp_mc1lm_inpath_para_audio[] = { //¶ÔÓ¦ÓÚMic1lp_Mic1lmÊäÈëͨµÀ
++ {"MIC1LM P-Terminal",{"Off"}},
++ {"MIC1RP P-Terminal",{"Off"}},
++ {"MIC1LP P-Terminal",{"FFR 10 Ohm"}},
++ {"MIC1LM M-Terminal",{"FFR 10 Ohm"}},
++
++};
++
++static struct audio_para_conf mic1rp_inpath_para_audio[] = {//¶ÔÓ¦ÓÚMic1rpÊäÈëͨµÀ
++ {"MIC1LM P-Terminal",{"Off"}},
++ {"MIC1RP P-Terminal",{"FFR 10 Ohm"}},
++ {"MIC1LP P-Terminal",{"Off"}},
++ {"MIC1LM M-Terminal",{"Off"}},
++};
++
++static struct audio_para_conf handset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++ {"Speaker Switch",{"0"}},
++ {"DAC Playback Volume",{"129","129"}},
++ {"HP Left Switch",{"1"}},
++ {"HP Right Switch",{"1"}},
++ {"HP Driver Playback Volume",{"7","7"}},
++ {"MIC1LM P-Terminal",{"Off"}},
++ {"MIC1RP P-Terminal",{"Off"}},
++ {"MIC1LP P-Terminal",{"FFR 10 Ohm"}},
++ {"MIC1LM M-Terminal",{"FFR 10 Ohm"}},
++ {"ADC Capture Volume",{"24"}},
++ {"voice processing path select",{"handset"}},
++
++};
++static struct audio_para_conf headset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ Mic1rpÊäÈëͨµÀ
++ {"Speaker Switch",{"0"}},
++ {"DAC Playback Volume ",{"129","129"}},
++ {"HP Left Switch",{"1"}},
++ {"HP Right Switch",{"1"}},
++ {"HP Driver Playback Switch",{"7","7"}}, //7dB
++ {"MIC1LM P-Terminal",{"Off"}},
++ {"MIC1RP P-Terminal",{"FFR 10 Ohm"}},
++ {"MIC1LP P-Terminal",{"Off"}},
++ {"MIC1LM M-Terminal",{"Off"}},
++ {"ADC Capture Volume",{"24"}},
++ {"voice processing select",{"headset"}},
++};
++
++static struct audio_para_conf spk_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++
++ {"DAC Playback Volume",{"124","124"}}, //-1.5dB
++ {"Speaker Switch",{"1"}},
++ {"Speaker Driver Playback Volume",{"2"}}, //18dB
++ {"HP Left Switch",{"0"}},
++ {"HP Right Switch",{"0"}},
++ {"MIC1LM P-Terminal",{"Off"}},
++ {"MIC1RP P-Terminal",{"Off"}},
++ {"MIC1LP P-Terminal",{"FFR 10 Ohm"}},
++ {"MIC1LM M-Terminal",{"FFR 10 Ohm"}},
++ {"ADC Capture Volume",{"24"}},
++ {"voice processing path select",{"speak"}},
++};
++
++static struct audio_para_conf output_dac_vol = {"DAC Playback Volume",{"24"}};
++
++static struct audio_para_conf input_adc_vol = {"ADC Capture Volume",{"129","129"}};
++
++static int sig_close = 1;
++
++static int s_outpath = T_OUTPUT_SPEAKER;
++static int s_inpath = T_INPUT_MICLP;
++static int s_invol = T_INPUT_VOL_0DB;
++static int s_outvol = T_OUTPUT_VOL_0DB;
++
++void stream_close(int sig)
++{
++ /* allow the stream to be closed gracefully */
++ signal(sig, SIG_IGN);
++ sig_close = 0;
++}
++
++static void tinymix_set_value_test(struct mixer *mixer, const char *control,
++ char **values)
++{
++ struct mixer_ctl *ctl;
++ enum mixer_ctl_type type;
++ unsigned int num_ctl_values;
++ unsigned int i;
++
++ if (isdigit(control[0]))
++ ctl = mixer_get_ctl(mixer, atoi(control));
++ else
++ ctl = mixer_get_ctl_by_name(mixer, control);
++
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return;
++ }
++
++ type = mixer_ctl_get_type(ctl);
++ num_ctl_values = mixer_ctl_get_num_values(ctl);
++
++ if (isdigit(values[0][0])) {
++
++ for (i = 0; i < num_ctl_values; i++) {
++ if (mixer_ctl_set_value(ctl, i, atoi(values[i]))) {
++ fprintf(stderr, "Error: invalid value for index %d\n", i);
++ return;
++ }
++ }
++
++ } else {
++ if (type == MIXER_CTL_TYPE_ENUM) {
++ /*if (num_values != 1) {
++ fprintf(stderr, "Enclose strings in quotes and try again\n");
++ return;
++ }*/
++ if (mixer_ctl_set_enum_by_string(ctl, values[0]))
++ fprintf(stderr, "Error: invalid enum value\n");
++ } else {
++ fprintf(stderr, "Error: only enum types can be set with strings\n");
++ }
++ }
++}
++
++int mix_set_outputpath(struct mixer *mixer, int path)
++{
++ int i;
++ for(i = 0;i<ARRAY_SIZE(common_out_para_audio);i++)
++ {
++ tinymix_set_value_test(mixer,common_out_para_audio[i].control,common_out_para_audio[i].values);
++ }
++ switch(path)
++ {
++ case T_OUTPUT_RECEIVER:
++ for(i = 0;i<ARRAY_SIZE(hp_outpath_para_audio);i++)
++ {
++ tinymix_set_value_test(mixer,hp_outpath_para_audio[i].control,hp_outpath_para_audio[i].values);
++ }
++ break;
++ case T_OUTPUT_SPEAKER:
++ for(i = 0;i<ARRAY_SIZE(spk_outpath_para_audio);i++)
++ {
++ tinymix_set_value_test(mixer,spk_outpath_para_audio[i].control,spk_outpath_para_audio[i].values);
++ }
++ break;
++ default:
++ break;
++ }
++
++ return 0;
++}
++
++int mix_set_inputpath(struct mixer *mixer, int path)
++{
++ int i;
++ for(i = 0;i<ARRAY_SIZE(common_in_para_audio);i++)
++ {
++ tinymix_set_value_test(mixer,common_in_para_audio[i].control,common_in_para_audio[i].values);
++ }
++ switch(path)
++ {
++ case T_INPUT_MICLP:
++ for(i = 0;i<ARRAY_SIZE(mic1lp_mc1lm_inpath_para_audio);i++)
++ {
++ tinymix_set_value_test(mixer,mic1lp_mc1lm_inpath_para_audio[i].control,mic1lp_mc1lm_inpath_para_audio[i].values);
++ }
++ break;
++ case T_INPUT_MICRP:
++ for(i = 0;i<ARRAY_SIZE(mic1rp_inpath_para_audio);i++)
++ {
++ tinymix_set_value_test(mixer,mic1rp_inpath_para_audio[i].control,mic1rp_inpath_para_audio[i].values);
++ }
++ break;
++ default:
++ break;
++ }
++
++ return 0;
++}
++
++int mix_set_inputvol(struct mixer *mixer, int volume)
++{
++
++ struct mixer_ctl *ctl = input_adc_vol.control;
++ enum mixer_ctl_type type;
++ unsigned int num_ctl_values;
++ unsigned int i;
++
++ ctl = mixer_get_ctl_by_name(mixer, ctl);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return;
++ }
++
++// int value = atoi(input_adc_vol.values[0]);
++// mixer_ctl_set_value(ctl, 0, value);
++ mixer_ctl_set_value(ctl, 0, volume);
++
++ return 0;
++}
++
++int mix_set_outputvol(struct mixer *mixer, int volume)
++{
++ struct mixer_ctl *ctl = output_dac_vol.control;
++ enum mixer_ctl_type type;
++ unsigned int i;
++
++ ctl = mixer_get_ctl_by_name(mixer, ctl);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return;
++ }
++
++ mixer_ctl_set_value(ctl, 0, volume);
++ mixer_ctl_set_value(ctl, 1, volume);
++// int value = atoi(output_dac_vol.values[0]);
++// mixer_ctl_set_value(ctl, 0, value);
++// value = atoi(output_dac_vol.values[1]);
++// mixer_ctl_set_value(ctl, 1, value);
++
++ return 0;
++}
++
++int mix_set_output_mute(struct mixer *mixer, bool enable)
++{
++ struct mixer_ctl *ctl = "DAC Mute";
++ enum mixer_ctl_type type;
++ unsigned int i;
++ printf("mix_set_output_mute %d\n",enable);
++
++ ctl = mixer_get_ctl_by_name(mixer, ctl);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return;
++ }
++ mixer_ctl_set_value(ctl, 0, enable);
++ mixer_ctl_set_value(ctl, 1, enable);
++}
++
++int mix_set_input_mute(struct mixer *mixer, bool enable)
++{
++ struct mixer_ctl *ctl = "ADC Capture Switch";
++ enum mixer_ctl_type type;
++ unsigned int i;
++
++ ctl = mixer_get_ctl_by_name(mixer, ctl);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return;
++ }
++
++ mixer_ctl_set_value(ctl, 0, !enable);
++}
++
++int check_param(struct pcm_params *params, unsigned int param, unsigned int value,
++ char *param_name, char *param_unit)
++{
++ unsigned int min;
++ unsigned int max;
++ int is_within_bounds = 1;
++
++ min = pcm_params_get_min(params, param);
++ if (value < min) {
++ fprintf(stderr, "%s is %u%s, device only supports >= %u%s\n", param_name, value,
++ param_unit, min, param_unit);
++ is_within_bounds = 0;
++ }
++
++ max = pcm_params_get_max(params, param);
++ if (value > max) {
++ fprintf(stderr, "%s is %u%s, device only supports <= %u%s\n", param_name, value,
++ param_unit, max, param_unit);
++ is_within_bounds = 0;
++ }
++
++ return is_within_bounds;
++}
++
++int sample_is_playable(unsigned int card, unsigned int device, unsigned int channels,
++ unsigned int rate, unsigned int bits, unsigned int period_size,
++ unsigned int period_count)
++{
++ struct pcm_params *params;
++ int can_play;
++
++ params = pcm_params_get(card, device, PCM_OUT);
++ if (params == NULL) {
++ fprintf(stderr, "Unable to open PCM device %u.\n", device);
++ return 0;
++ }
++
++ can_play = check_param(params, PCM_PARAM_RATE, rate, "Sample rate", "Hz");
++ can_play &= check_param(params, PCM_PARAM_CHANNELS, channels, "Sample", " channels");
++ can_play &= check_param(params, PCM_PARAM_SAMPLE_BITS, bits, "Bitrate", " bits");
++ can_play &= check_param(params, PCM_PARAM_PERIOD_SIZE, period_size, "Period size", "Hz");
++ can_play &= check_param(params, PCM_PARAM_PERIODS, period_count, "Period count", "Hz");
++
++ pcm_params_free(params);
++
++ return can_play;
++}
++
++void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,
++ unsigned int rate, unsigned int bits, unsigned int period_size,
++ unsigned int period_count)
++{
++ struct pcm_config config;
++ struct pcm *pcm;
++ char *buffer;
++ int size;
++ int num_read;
++
++ memset(&config, 0, sizeof(config));
++ config.channels = channels;
++ config.rate = rate;
++ config.period_size = period_size;
++ config.period_count = period_count;
++ if (bits == 32)
++ config.format = PCM_FORMAT_S32_LE;
++ else if (bits == 16)
++ config.format = PCM_FORMAT_S16_LE;
++ config.start_threshold = 0;
++ config.stop_threshold = 0;
++ config.silence_threshold = 0;
++
++ if (!sample_is_playable(card, device, channels, rate, bits, period_size, period_count)) {
++ return;
++ }
++
++ pcm = pcm_open(card, device, PCM_OUT, &config);
++ if (!pcm || !pcm_is_ready(pcm)) {
++ fprintf(stderr, "Unable to open PCM device %u (%s)\n",
++ device, pcm_get_error(pcm));
++ return;
++ }
++
++ size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
++ buffer = malloc(size);
++ if (!buffer) {
++ fprintf(stderr, "Unable to allocate %d bytes\n", size);
++ free(buffer);
++ pcm_close(pcm);
++ return;
++ }
++
++ printf("Playing sample: %u ch, %u hz, %u bit\n", channels, rate, bits);
++
++ /* catch ctrl-c to shutdown cleanly */
++ signal(SIGINT, stream_close);
++
++ do {
++ num_read = fread(buffer, 1, size, file);
++ if (num_read > 0) {
++ if (pcm_write(pcm, buffer, num_read)) {
++ fprintf(stderr, "Error playing sample\n");
++ break;
++ }
++ }
++ } while (sig_close && num_read > 0);
++
++ free(buffer);
++ pcm_close(pcm);
++}
++
++unsigned int capture_sample(FILE *file, unsigned int card, unsigned int device,
++ unsigned int channels, unsigned int rate,
++ enum pcm_format format, unsigned int period_size,
++ unsigned int period_count)
++{
++ struct pcm_config config;
++ struct pcm *pcm;
++ char *buffer;
++ unsigned int size;
++ unsigned int bytes_read = 0;
++
++ memset(&config, 0, sizeof(config));
++ config.channels = channels;
++ config.rate = rate;
++ config.period_size = period_size;
++ config.period_count = period_count;
++ config.format = format;
++ config.start_threshold = 0;
++ config.stop_threshold = 0;
++ config.silence_threshold = 0;
++
++ pcm = pcm_open(card, device, PCM_IN, &config);
++ if (!pcm || !pcm_is_ready(pcm)) {
++ fprintf(stderr, "Unable to open PCM device (%s)\n",
++ pcm_get_error(pcm));
++ return 0;
++ }
++
++ size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
++ buffer = malloc(size);
++ if (!buffer) {
++ fprintf(stderr, "Unable to allocate %d bytes\n", size);
++ free(buffer);
++ pcm_close(pcm);
++ return 0;
++ }
++
++ printf("Capturing sample: %u ch, %u hz, %u bit\n", channels, rate,
++ pcm_format_to_bits(format));
++
++ while (sig_close && !pcm_read(pcm, buffer, size)) {
++ if (fwrite(buffer, 1, size, file) != size) {
++ fprintf(stderr,"Error capturing sample\n");
++ break;
++ }
++ bytes_read += size;
++ if (bytes_read>=300000)
++ break;
++ }
++
++ free(buffer);
++ pcm_close(pcm);
++ return pcm_bytes_to_frames(pcm, bytes_read);
++}
++
++int main(int argc, char **argv)
++{
++ FILE *file;
++ struct wav_header header;
++ unsigned int card = 0;
++ unsigned int device = 0;
++ unsigned int channels = 2;
++ unsigned int rate = 44100;
++ unsigned int bits = 16;
++ unsigned int frames;
++ unsigned int period_size = 1024;
++ unsigned int period_count = 4;
++ enum pcm_format format;
++
++ struct riff_wave_header riff_wave_header;
++ struct chunk_header chunk_header;
++ struct chunk_fmt chunk_fmt;
++ char *filename;
++ int more_chunks = 1;
++ struct mixer *mixer;
++
++
++ if (argc < 2) {
++ fprintf(stderr, "Usage: %s cap file.wav [-D card] [-d device] [-c channels] "
++ "[-r rate] [-b bits] [-p period_size] [-n n_periods]\n", argv[0]);
++ fprintf(stderr, "Usage: %s play file.wav [-D card] [-d device] [-p period_size]"
++ " [-n n_periods] \n", argv[0]);
++ return 1;
++ }
++
++ if (strcmp(argv[1], "play") == 0) {
++ mixer = mixer_open(card);
++ if (!mixer) {
++ fprintf(stderr, "Failed to open mixer\n");
++ return -1;
++ }
++ mix_set_outputpath(mixer, T_OUTPUT_SPEAKER);
++ mix_set_outputvol(mixer, T_OUTPUT_VOL_0DB);
++ // mix_set_output_mute(mixer,false);
++ mixer_close(mixer);
++
++ filename = argv[2];
++ file = fopen(filename, "rb");
++ if (!file) {
++ fprintf(stderr, "Unable to open file '%s'\n", filename);
++ return 1;
++ }
++
++ fread(&riff_wave_header, sizeof(riff_wave_header), 1, file);
++ if ((riff_wave_header.riff_id != ID_RIFF) ||
++ (riff_wave_header.wave_id != ID_WAVE)) {
++ fprintf(stderr, "Error: '%s' is not a riff/wave file\n", filename);
++ fclose(file);
++ return 1;
++ }
++
++ do {
++ fread(&chunk_header, sizeof(chunk_header), 1, file);
++
++ switch (chunk_header.id) {
++ case ID_FMT:
++ fread(&chunk_fmt, sizeof(chunk_fmt), 1, file);
++ /* If the format header is larger, skip the rest */
++ if (chunk_header.sz > sizeof(chunk_fmt))
++ fseek(file, chunk_header.sz - sizeof(chunk_fmt), SEEK_CUR);
++ break;
++ case ID_DATA:
++ /* Stop looking for chunks */
++ more_chunks = 0;
++ break;
++ default:
++ /* Unknown chunk, skip bytes */
++ fseek(file, chunk_header.sz, SEEK_CUR);
++ }
++ } while (more_chunks);
++
++ /* parse command line arguments */
++ argv += 3;
++ while (*argv) {
++ if (strcmp(*argv, "-d") == 0) {
++ argv++;
++ if (*argv)
++ device = atoi(*argv);
++ }
++ if (strcmp(*argv, "-p") == 0) {
++ argv++;
++ if (*argv)
++ period_size = atoi(*argv);
++ }
++ if (strcmp(*argv, "-n") == 0) {
++ argv++;
++ if (*argv)
++ period_count = atoi(*argv);
++ }
++ if (strcmp(*argv, "-D") == 0) {
++ argv++;
++ if (*argv)
++ card = atoi(*argv);
++ }
++ if (*argv)
++ argv++;
++ }
++
++ play_sample(file, card, device, chunk_fmt.num_channels, chunk_fmt.sample_rate,
++ chunk_fmt.bits_per_sample, period_size, period_count);
++
++ fclose(file);
++
++ }else if(strcmp(argv[1], "cap") == 0) {
++ mixer = mixer_open(card);
++ if (!mixer) {
++ fprintf(stderr, "Failed to open mixer\n");
++ return -1;
++ }
++ mix_set_inputpath(mixer, T_INPUT_MICLP);
++ mix_set_inputvol(mixer, T_INPUT_VOL_0DB);
++ mixer_close(mixer);
++
++ file = fopen(argv[2], "wb");
++ if (!file) {
++ fprintf(stderr, "Unable to create file '%s'\n", argv[1]);
++ return 1;
++ }
++
++ /* parse command line arguments */
++ argv += 3;
++ while (*argv) {
++ if (strcmp(*argv, "-d") == 0) {
++ argv++;
++ if (*argv)
++ device = atoi(*argv);
++ } else if (strcmp(*argv, "-c") == 0) {
++ argv++;
++ if (*argv)
++ channels = atoi(*argv);
++ } else if (strcmp(*argv, "-r") == 0) {
++ argv++;
++ if (*argv)
++ rate = atoi(*argv);
++ } else if (strcmp(*argv, "-b") == 0) {
++ argv++;
++ if (*argv)
++ bits = atoi(*argv);
++ } else if (strcmp(*argv, "-D") == 0) {
++ argv++;
++ if (*argv)
++ card = atoi(*argv);
++ } else if (strcmp(*argv, "-p") == 0) {
++ argv++;
++ if (*argv)
++ period_size = atoi(*argv);
++ } else if (strcmp(*argv, "-n") == 0) {
++ argv++;
++ if (*argv)
++ period_count = atoi(*argv);
++ }
++ if (*argv)
++ argv++;
++ }
++
++ header.riff_id = ID_RIFF;
++ header.riff_sz = 0;
++ header.riff_fmt = ID_WAVE;
++ header.fmt_id = ID_FMT;
++ header.fmt_sz = 16;
++ header.audio_format = FORMAT_PCM;
++ header.num_channels = channels;
++ header.sample_rate = rate;
++
++ switch (bits) {
++ case 32:
++ format = PCM_FORMAT_S32_LE;
++ break;
++ case 24:
++ format = PCM_FORMAT_S24_LE;
++ break;
++ case 16:
++ format = PCM_FORMAT_S16_LE;
++ break;
++ default:
++ fprintf(stderr, "%d bits is not supported.\n", bits);
++ return 1;
++ }
++
++ header.bits_per_sample = pcm_format_to_bits(format);
++ header.byte_rate = (header.bits_per_sample / 8) * channels * rate;
++ header.block_align = channels * (header.bits_per_sample / 8);
++ header.data_id = ID_DATA;
++
++ /* leave enough room for header */
++ fseek(file, sizeof(struct wav_header), SEEK_SET);
++
++ /* install signal handler and begin capturing */
++ signal(SIGINT, stream_close);
++ frames = capture_sample(file, card, device, header.num_channels,
++ header.sample_rate, format,
++ period_size, period_count);
++ printf("Captured %d frames\n", frames);
++
++ /* write header now all information is known */
++ header.data_sz = frames * header.block_align;
++ header.riff_sz = header.data_sz + sizeof(header) - 8;
++ fseek(file, 0, SEEK_SET);
++ fwrite(&header, sizeof(struct wav_header), 1, file);
++
++ fclose(file);
++ }
++
++ return 0;
++}
+diff --git a/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/audio_mixer_ctrl.c b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/audio_mixer_ctrl.c
+new file mode 100755
+index 0000000..65c7e3c
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/audio_mixer_ctrl.c
+@@ -0,0 +1,3017 @@
++#include <stdio.h>
++#include <unistd.h>
++#include <string.h>
++#include <fcntl.h>
++#include <stdint.h>
++#include <stdbool.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <ctype.h>
++#include <tinyalsa/asoundlib.h>
++#include <sound/asound.h>
++#include <tinyalsa/audio_mixer_ctrl.h>
++
++#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
++
++struct audio_para_conf {
++ const char *control;
++ char *values[2];
++};
++
++
++#if defined _USE_CODEC_TI3100
++
++
++enum t_output_vol {
++ T_OUTPUT_VOL_MINUS_63_5DB = 0,
++ T_OUTPUT_VOL_MINUS_63DB = 1,
++ T_OUTPUT_VOL_MINUS_27DB = 73,
++ T_OUTPUT_VOL_MINUS_24DB = 79,
++ T_OUTPUT_VOL_MINUS_21DB = 85,
++ T_OUTPUT_VOL_MINUS_18DB = 91,
++ T_OUTPUT_VOL_MINUS_15DB = 97,
++ T_OUTPUT_VOL_MINUS_12DB = 103,
++ T_OUTPUT_VOL_MINUS_9DB = 109,
++ T_OUTPUT_VOL_MINUS_6DB = 115,
++ T_OUTPUT_VOL_MINUS_3DB = 121,
++ T_OUTPUT_VOL_MINUS_2DB = 123,
++ T_OUTPUT_VOL_MINUS_1DB = 125,
++ T_OUTPUT_VOL_0DB = 127,
++ T_OUTPUT_VOL_1DB = 129,
++ T_OUTPUT_VOL_2DB = 131,
++ T_OUTPUT_VOL_3DB = 133,
++ T_OUTPUT_VOL_6DB = 139,
++ T_OUTPUT_VOL_9DB = 145,
++ T_OUTPUT_VOL_12DB = 151,
++ T_OUTPUT_VOL_24DB = 175,
++};
++
++enum t_input_vol {
++ T_INPUT_VOL_MINUS_12DB = 0,
++ T_INPUT_VOL_MINUS_7DB = 10,
++ T_INPUT_VOL_MINUS_6DB = 12,
++ T_INPUT_VOL_MINUS_5DB = 14,
++ T_INPUT_VOL_MINUS_4DB = 16,
++ T_INPUT_VOL_MINUS_3DB = 18,
++ T_INPUT_VOL_MINUS_2DB = 20,
++ T_INPUT_VOL_MINUS_1DB = 22,
++ T_INPUT_VOL_0DB = 24,
++ T_INPUT_VOL_1DB = 26,
++ T_INPUT_VOL_2DB = 28,
++ T_INPUT_VOL_3DB = 30,
++ T_INPUT_VOL_20DB = 64,
++};
++
++static struct audio_para_conf init_default_para[] = { //¿ª»ú³õʼ»¯µ÷ÓÃ
++ {"Mic PGA Capture Volume", {"40"}},
++ {"ADC Mute", {"0"}},
++ {"ADC Fine Capture Volume", {"0"}},
++ {"Speaker Analog Playback Volume", {"127"}},
++ {"Speaker Driver Playback Switch", {"1"}},
++ {"DAC Left Input", {"Mono"}},
++ {"DAC Right Input", {"Mono"}},
++ {"Output Right From Right DAC", {"1"}},
++ {"Output Left From Left DAC", {"1"}},
++ {"HP Analog Playback Volume", {"127", "127"}},
++ {"HP Driver Playback Switch", {"1", "1"}}, //7dB
++};
++
++#ifdef _USE_7520V3_PHONE_TYPE_FWP
++static struct audio_para_conf common_out_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ {"Speaker Analog Playback Volume", {"127"}},
++ {"Speaker Driver Playback Switch", {"1"}},
++ {"DAC Left Input", {"Mono"}},
++ {"DAC Right Input", {"Mono"}},
++ {"Output Right From Right DAC", {"1"}},
++ {"Output Left From Left DAC", {"1"}},
++ {"HP Analog Playback Volume", {"127", "127"}},
++ {"HP Driver Playback Switch", {"1", "1"}}, //7dB
++};
++
++static struct audio_para_conf common_in_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ {"Mic PGA Capture Volume", {"12"}},
++ {"ADC Mute", {"0"}},
++ {"ADC Fine Capture Volume", {"0"}},
++
++};
++
++static struct audio_para_conf hp_outpath_para_audio[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ
++ {"Speaker Switch", {"0"}},
++ {"HP Left Switch", {"1"}},
++ {"HP Right Switch", {"1"}},
++ {"HP Driver Playback Volume", {"0", "0"}},
++};
++
++static struct audio_para_conf spk_outpath_para_audio[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀ
++ {"Speaker Switch", {"1"}},
++ {"Speaker Driver Playback Volume", {"2"}}, //18dB
++ {"HP Left Switch", {"0"}},
++ {"HP Right Switch", {"0"}},
++};
++
++static struct audio_para_conf main_mic_inpath_para_audio[] = { //¶ÔÓ¦ÓÚMic1lp_Mic1lmÊäÈëͨµÀ
++ {"MIC1LM P-Terminal", {"Off"}},
++ {"MIC1RP P-Terminal", {"Off"}},
++ {"MIC1LP P-Terminal", {"FFR 10 Ohm"}},
++ {"MIC1LM M-Terminal", {"FFR 10 Ohm"}},
++
++};
++
++static struct audio_para_conf aux_mic_inpath_para_audio[] = {//¶ÔÓ¦ÓÚMic1rpÊäÈëͨµÀ
++ {"MIC1LM P-Terminal", {"Off"}},
++ {"MIC1RP P-Terminal", {"FFR 10 Ohm"}},
++ {"MIC1LP P-Terminal", {"Off"}},
++ {"MIC1LM M-Terminal", {"Off"}},
++};
++
++static struct audio_para_conf handset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++ {"Mic PGA Capture Volume", {"12"}},
++ //{"ADC Mute", {"0"}},
++ //{"ADC Fine Capture Volume", {"0"}},
++ {"DAC Left Input", {"Mono"}},
++ {"DAC Right Input", {"Mono"}},
++ {"Output Right From Right DAC", {"1"}},
++ {"Output Left From Left DAC", {"1"}},
++ {"HP Analog Playback Volume", {"127", "127"}},
++ {"HP Driver Playback Switch", {"1", "1"}}, //7dB
++ {"Speaker Switch", {"0"}},
++ {"DAC Playback Volume", {"129", "129"}},
++ {"HP Left Switch", {"1"}},
++ {"HP Right Switch", {"1"}},
++ {"HP Driver Playback Volume", {"5", "5"}},
++ {"MIC1LM P-Terminal", {"Off"}},
++ {"MIC1RP P-Terminal", {"Off"}},
++ {"MIC1LP P-Terminal", {"FFR 10 Ohm"}},
++ {"MIC1LM M-Terminal", {"FFR 10 Ohm"}},
++ {"ADC Capture Volume", {"24"}},
++#ifndef USE_CAP_SUPPORT
++
++ {"voice processing path select", {"handset"}}, // handset speak headset bluetooth
++#endif
++};
++
++static struct audio_para_conf headset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ Mic1rpÊäÈëͨµÀ
++ {"Mic PGA Capture Volume", {"40"}},
++ //{"ADC Mute", {"0"}},
++ //{"ADC Fine Capture Volume", {"0"}},
++ {"DAC Left Input", {"Mono"}},
++ {"DAC Right Input", {"Mono"}},
++ {"Output Right From Right DAC", {"1"}},
++ {"Output Left From Left DAC", {"1"}},
++ {"HP Analog Playback Volume", {"127", "127"}},
++ {"HP Driver Playback Switch", {"1", "1"}}, //7dB
++ {"Speaker Switch", {"0"}},
++ {"DAC Playback Volume ", {"129", "129"}},
++ {"HP Left Switch", {"1"}},
++ {"HP Right Switch", {"1"}},
++ {"HP Driver Playback Switch", {"7", "7"}}, //7dB
++ {"MIC1LM P-Terminal", {"Off"}},
++ {"MIC1RP P-Terminal", {"FFR 10 Ohm"}},
++ {"MIC1LP P-Terminal", {"Off"}},
++ {"MIC1LM M-Terminal", {"Off"}},
++ {"ADC Capture Volume", {"24"}},
++#ifndef USE_CAP_SUPPORT
++ {"voice processing path select", {"headset"}}, // handset speak headset bluetooth
++#endif
++};
++
++static struct audio_para_conf spk_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++ {"Mic PGA Capture Volume", {"12"}},
++ //{"ADC Mute", {"0"}},
++ //{"ADC Fine Capture Volume", {"0"}},
++ {"Speaker Analog Playback Volume", {"127"}},
++ {"Speaker Driver Playback Switch", {"1"}},
++ {"DAC Left Input", {"Mono"}},
++ {"DAC Right Input", {"Mono"}},
++ {"Output Right From Right DAC", {"1"}},
++ {"Output Left From Left DAC", {"1"}},
++ {"DAC Playback Volume", {"124", "124"}}, //-1.5dB
++ {"Speaker Switch", {"1"}},
++ {"Speaker Driver Playback Volume", {"0"}}, //18dB
++ {"HP Left Switch", {"0"}},
++ {"HP Right Switch", {"0"}},
++ {"MIC1LM P-Terminal", {"Off"}},
++ {"MIC1RP P-Terminal", {"Off"}},
++ {"MIC1LP P-Terminal", {"FFR 10 Ohm"}},
++ {"MIC1LM M-Terminal", {"FFR 10 Ohm"}},
++ {"ADC Capture Volume", {"24"}},
++#ifndef USE_CAP_SUPPORT
++
++ {"voice processing path select", {"speak"}}, // handset speak headset bluetooth
++#endif
++};
++
++#else
++static struct audio_para_conf common_out_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ {"Speaker Analog Playback Volume", {"127"}},
++ {"Speaker Driver Playback Switch", {"1"}},
++ {"DAC Left Input", {"Mono"}},
++ {"DAC Right Input", {"Mono"}},
++ {"Output Right From Right DAC", {"1"}},
++ {"Output Left From Left DAC", {"1"}},
++ {"HP Analog Playback Volume", {"127", "127"}},
++ {"HP Driver Playback Switch", {"1", "1"}}, //7dB
++};
++
++static struct audio_para_conf common_in_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ {"Mic PGA Capture Volume", {"40"}},
++ {"ADC Mute", {"0"}},
++ {"ADC Fine Capture Volume", {"0"}},
++
++};
++
++static struct audio_para_conf hp_outpath_para_audio[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ
++ {"Speaker Switch", {"0"}},
++ {"HP Left Switch", {"1"}},
++ {"HP Right Switch", {"1"}},
++ {"HP Driver Playback Volume", {"0", "0"}},
++};
++
++static struct audio_para_conf spk_outpath_para_audio[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀ
++ {"Speaker Switch", {"1"}},
++ {"Speaker Driver Playback Volume", {"2"}}, //18dB
++ {"HP Left Switch", {"0"}},
++ {"HP Right Switch", {"0"}},
++};
++
++static struct audio_para_conf main_mic_inpath_para_audio[] = { //¶ÔÓ¦ÓÚMic1lp_Mic1lmÊäÈëͨµÀ
++ {"MIC1LM P-Terminal", {"Off"}},
++ {"MIC1RP P-Terminal", {"Off"}},
++ {"MIC1LP P-Terminal", {"FFR 10 Ohm"}},
++ {"MIC1LM M-Terminal", {"FFR 10 Ohm"}},
++
++};
++
++static struct audio_para_conf aux_mic_inpath_para_audio[] = {//¶ÔÓ¦ÓÚMic1rpÊäÈëͨµÀ
++ {"MIC1LM P-Terminal", {"Off"}},
++ {"MIC1RP P-Terminal", {"FFR 10 Ohm"}},
++ {"MIC1LP P-Terminal", {"Off"}},
++ {"MIC1LM M-Terminal", {"Off"}},
++};
++
++static struct audio_para_conf handset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++ {"Mic PGA Capture Volume", {"40"}},//analog gain control from 0 dB to 59.5 dB in steps of 0.5 dB
++ {"ADC Mute", {"0"}},//ADC muting
++ {"DAC Mute", {"0","0"}},//DAC muting and setting up a master gain control to control both channels occurs
++ //{"ADC Fine Capture Volume", {"0"}},
++ {"DAC Left Input", {"Mono"}},
++ {"DAC Right Input", {"Mono"}},
++ {"Output Right From Right DAC", {"1"}},
++ {"Output Left From Left DAC", {"1"}},//"1" means DAC_L is firstly routed to the left-channel mixer amplifier, then routed HPL driver
++ {"HP Analog Playback Volume", {"114", "114"}},//Analog Volume Control for Headphone and Speaker Outputs(D0~D6)
++ {"HP Driver Playback Switch", {"1", "1"}}, // HPL/HPR driver is not muted
++ {"Speaker Switch", {"0"}},//Analog Volume Control for Speaker Outputs(D7)
++ {"DAC Playback Volume", {"135", "135"}},//DAC volume: -127 to 48??//0627Ô½´óÔöÒæÔ½´ó
++ {"HP Left Switch", {"1"}},//Analog Volume Control for Headphone Outputs(D7)
++ {"HP Right Switch", {"1"}},
++ {"HP Driver Playback Volume", {"9", "9"}},//HPL/HPR driver is 9dB(0~9)
++ {"MIC1LM P-Terminal", {"Off"}},
++ {"MIC1RP P-Terminal", {"Off"}},
++ {"MIC1LP P-Terminal", {"FFR 10 Ohm"}},
++ {"MIC1LM M-Terminal", {"FFR 10 Ohm"}},
++ {"ADC Capture Volume", {"24"}},
++#ifndef USE_CAP_SUPPORT
++ {"voice processing path select", {"handset"}}, // handset speak headset bluetooth
++#endif
++};
++
++static struct audio_para_conf headset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ Mic1rpÊäÈëͨµÀ
++ {"Mic PGA Capture Volume", {"40"}},
++ {"ADC Mute", {"0"}},
++ {"DAC Mute", {"0","0"}},
++ //{"ADC Fine Capture Volume", {"0"}},
++ {"DAC Left Input", {"Mono"}},
++ {"DAC Right Input", {"Mono"}},
++ {"Output Right From Right DAC", {"1"}},
++ {"Output Left From Left DAC", {"1"}},
++ {"HP Analog Playback Volume", {"127", "127"}},
++ {"HP Driver Playback Switch", {"1", "1"}}, //7dB
++ {"Speaker Switch", {"0"}},
++ {"DAC Playback Volume ", {"129", "129"}},
++ {"HP Left Switch", {"1"}},
++ {"HP Right Switch", {"1"}},
++ {"HP Driver Playback Switch", {"7", "7"}}, //7dB
++ {"MIC1LM P-Terminal", {"Off"}},
++ {"MIC1RP P-Terminal", {"FFR 10 Ohm"}},
++ {"MIC1LP P-Terminal", {"Off"}},
++ {"MIC1LM M-Terminal", {"Off"}},
++ {"ADC Capture Volume", {"24"}},
++#ifndef USE_CAP_SUPPORT
++ {"voice processing path select", {"headset"}}, // handset speak headset bluetooth
++#endif
++};
++
++static struct audio_para_conf spk_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++ {"Mic PGA Capture Volume", {"20"}},
++ {"ADC Mute", {"0"}},
++ {"DAC Mute", {"0","0"}},
++ //{"ADC Fine Capture Volume", {"0"}},
++ {"Speaker Analog Playback Volume", {"116"}},
++ {"Speaker Driver Playback Switch", {"1"}},
++ {"DAC Left Input", {"Mono"}},
++ {"DAC Right Input", {"Mono"}},
++ {"Output Right From Right DAC", {"1"}},
++ {"Output Left From Left DAC", {"1"}},
++ {"DAC Playback Volume", {"130", "130"}}, //
++ {"Speaker Switch", {"1"}},
++ {"Speaker Driver Playback Volume", {"1"}}, //12dB //0~3 is 6dB~24dB(6-dB Steps)
++ {"HP Left Switch", {"0"}},
++ {"HP Right Switch", {"0"}},
++ {"MIC1LM P-Terminal", {"Off"}},
++ {"MIC1RP P-Terminal", {"Off"}},
++ {"MIC1LP P-Terminal", {"FFR 10 Ohm"}},
++ {"MIC1LM M-Terminal", {"FFR 10 Ohm"}},
++ {"ADC Capture Volume", {"24"}},
++#ifndef USE_CAP_SUPPORT
++
++ {"voice processing path select", {"speak"}}, // handset speak headset bluetooth
++#endif
++};
++
++#endif
++static struct audio_para_conf output_dac_vol = {"DAC Playback Volume", {"129","129"}};
++
++static struct audio_para_conf input_adc_vol = {"ADC Capture Volume", {"24"}};
++
++static struct audio_para_conf dac_mute = {"DAC Mute", {"1", "1"}};
++static struct audio_para_conf adc_mute = {"ADC Mute", {"1"}};
++
++static struct audio_para_conf spk_path_onoff[] = {
++ {"Speaker Switch", {"0"}},
++};
++static struct audio_para_conf rcv_path_onoff[] = {
++ {"HP Left Switch", {"0"}},
++ {"HP Right Switch", {"0"}},
++};
++static struct audio_para_conf earp_path_onoff[] = {
++ {"HP Left Switch", {"0"}},
++ {"HP Right Switch", {"0"}},
++};
++static int output_vol_conversion(int vol)
++{
++ switch(vol){
++ case T_AUDIO_OUTPUT_VOL_LEVEL_0:
++ return T_OUTPUT_VOL_MINUS_63_5DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_1:
++ return T_OUTPUT_VOL_MINUS_27DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_2:
++ return T_OUTPUT_VOL_MINUS_24DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_3:
++ return T_OUTPUT_VOL_MINUS_21DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_4:
++ return T_OUTPUT_VOL_MINUS_18DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_5:
++ return T_OUTPUT_VOL_MINUS_15DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_6:
++ return T_OUTPUT_VOL_MINUS_12DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_7:
++ return T_OUTPUT_VOL_MINUS_9DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_8:
++ return T_OUTPUT_VOL_MINUS_6DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_9:
++ return T_OUTPUT_VOL_MINUS_3DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_10:
++ return T_OUTPUT_VOL_0DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_11:
++ return T_OUTPUT_VOL_3DB;
++ default:
++ return T_OUTPUT_VOL_0DB;
++ }
++}
++
++
++static int input_vol_conversion(int vol)
++{
++ switch(vol) {
++ case T_AUDIO_INPUT_VOL_LEVEL_0:
++ return T_INPUT_VOL_MINUS_12DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_1:
++ return T_INPUT_VOL_MINUS_7DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_2:
++ return T_INPUT_VOL_MINUS_6DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_3:
++ return T_INPUT_VOL_MINUS_5DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_4:
++ return T_INPUT_VOL_MINUS_4DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_5:
++ return T_INPUT_VOL_MINUS_3DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_6:
++ return T_INPUT_VOL_MINUS_2DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_7:
++ return T_INPUT_VOL_MINUS_1DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_8:
++ return T_INPUT_VOL_0DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_9:
++ return T_INPUT_VOL_1DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_10:
++ return T_INPUT_VOL_2DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_11:
++ return T_INPUT_VOL_3DB;
++ default:
++ return T_INPUT_VOL_0DB;
++ }
++}
++#elif defined _USE_CODEC_ES8311
++static struct audio_para_conf init_default_para[] = { //¿ª»ú³õʼ»¯µ÷ÓÃ
++
++};
++
++static struct audio_para_conf common_out_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ //{"DAC Soft Mute Control", {"0"}},
++
++
++};
++
++
++static struct audio_para_conf common_in_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++
++ //{"Mic Gain Control", {"0"}},
++
++};
++
++static struct audio_para_conf hp_outpath_para_audio[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ
++ {"MIC PGA GAIN", {"10"}},
++ {"ADC SCALE", {"1"}},
++ {"DMIC TYPE", {"dmic at high level"}},
++ {"ADC RAMP RATE", {"4"}},
++ {"ADC SDP MUTE", {"0"}},
++ {"ADC INVERTED", {"0"}},
++ {"ADC SYNC", {"0"}},
++ {"ADC RAM CLR", {"0"}},
++ {"ADC VOLUME", {"191"}},
++ {"ALC ENABLE", {"0"}},
++ {"ALC AUTOMUTE TYPE", {"automute disabled"}},
++ {"ALC WIN SIZE", {"0"}},
++ {"ALC MAX LEVEL", {"0"}},
++ {"ALC MIN LEVEL", {"0"}},
++ {"ALC AUTOMUTE WINSIZE", {"0"}},
++ {"ALC AUTOMUTE GATE THRESHOLD", {"0"}},
++ {"ALC AUTOMUTE VOLUME", {"0"}},
++ {"ADC FS MODE", {"0"}},
++ {"DAC SDP MUTE", {"0"}},
++ {"DAC DEM MUTE", {"0"}},
++ {"DAC INVERT", {"0"}},
++ {"DAC RAM CLR", {"0"}},
++ {"DAC DSM MUTE", {"mute to 8"}},
++ {"DAC OFFSET", {"0"}},
++ {"DAC VOLUME", {"191"}},
++ {"DRC ENABLE", {"0"}},
++ {"DRC WIN SIZE", {"0"}},
++ {"DRC MAX LEVEL", {"0"}},
++ {"DRC MIN LEVEL", {"0"}},
++ {"DAC RAMP RATE", {"4"}},
++ {"AEC MODE", {"adc left, adc right"}},
++ {"ADC DATA TO DAC TEST MODE", {"disable"}},
++ {"MCLK INVERT", {"0"}},
++ {"BCLK INVERT", {"0"}},
++ {"MCLK SOURCE", {"from mclk pin"}},
++
++ {"DMIC MUX", {"DMIC DISABLE"}},
++ {"SDP OUT MUX", {"FROM ADC OUT"}},
++ {"DAC SDP SRC MUX", {"SELECT SDP LEFT DATA"}},
++
++
++
++};
++
++static struct audio_para_conf spk_outpath_para_audio[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀ
++ {"MIC PGA GAIN", {"10"}},
++ {"ADC SCALE", {"1"}},
++ {"DMIC TYPE", {"dmic at high level"}},
++ {"ADC RAMP RATE", {"4"}},
++ {"ADC SDP MUTE", {"0"}},
++ {"ADC INVERTED", {"0"}},
++ {"ADC SYNC", {"0"}},
++ {"ADC RAM CLR", {"0"}},
++ {"ADC VOLUME", {"191"}},
++ {"ALC ENABLE", {"0"}},
++ {"ALC AUTOMUTE TYPE", {"automute disabled"}},
++ {"ALC WIN SIZE", {"0"}},
++ {"ALC MAX LEVEL", {"0"}},
++ {"ALC MIN LEVEL", {"0"}},
++ {"ALC AUTOMUTE WINSIZE", {"0"}},
++ {"ALC AUTOMUTE GATE THRESHOLD", {"0"}},
++ {"ALC AUTOMUTE VOLUME", {"0"}},
++ {"ADC FS MODE", {"0"}},
++ {"DAC SDP MUTE", {"0"}},
++ {"DAC DEM MUTE", {"0"}},
++ {"DAC INVERT", {"0"}},
++ {"DAC RAM CLR", {"0"}},
++ {"DAC DSM MUTE", {"mute to 8"}},
++ {"DAC OFFSET", {"0"}},
++ {"DAC VOLUME", {"191"}},
++ {"DRC ENABLE", {"0"}},
++ {"DRC WIN SIZE", {"0"}},
++ {"DRC MAX LEVEL", {"0"}},
++ {"DRC MIN LEVEL", {"0"}},
++ {"DAC RAMP RATE", {"4"}},
++ {"AEC MODE", {"adc left, adc right"}},
++ {"ADC DATA TO DAC TEST MODE", {"disable"}},
++ {"MCLK INVERT", {"0"}},
++ {"BCLK INVERT", {"0"}},
++ {"MCLK SOURCE", {"from mclk pin"}},
++
++ {"DMIC MUX", {"DMIC DISABLE"}},
++ {"SDP OUT MUX", {"FROM ADC OUT"}},
++ {"DAC SDP SRC MUX", {"SELECT SDP LEFT DATA"}},
++
++
++};
++
++static struct audio_para_conf main_mic_inpath_para_audio[] = { //¶ÔÓ¦ÓÚMic1lp_Mic1lmÊäÈëͨµÀ
++
++ {"MIC PGA GAIN", {"10"}},
++ {"ADC SCALE", {"1"}},
++ {"DMIC TYPE", {"dmic at high level"}},
++ {"ADC RAMP RATE", {"4"}},
++ {"ADC SDP MUTE", {"0"}},
++ {"ADC INVERTED", {"0"}},
++ {"ADC SYNC", {"0"}},
++ {"ADC RAM CLR", {"0"}},
++ {"ADC VOLUME", {"191"}},
++ {"ALC ENABLE", {"0"}},
++ {"ALC AUTOMUTE TYPE", {"automute disabled"}},
++ {"ALC WIN SIZE", {"0"}},
++ {"ALC MAX LEVEL", {"0"}},
++ {"ALC MIN LEVEL", {"0"}},
++ {"ALC AUTOMUTE WINSIZE", {"0"}},
++ {"ALC AUTOMUTE GATE THRESHOLD", {"0"}},
++ {"ALC AUTOMUTE VOLUME", {"0"}},
++ {"ADC FS MODE", {"0"}},
++ {"DAC SDP MUTE", {"0"}},
++ {"DAC DEM MUTE", {"0"}},
++ {"DAC INVERT", {"0"}},
++ {"DAC RAM CLR", {"0"}},
++ {"DAC DSM MUTE", {"mute to 8"}},
++ {"DAC OFFSET", {"0"}},
++ {"DAC VOLUME", {"191"}},
++ {"DRC ENABLE", {"0"}},
++ {"DRC WIN SIZE", {"0"}},
++ {"DRC MAX LEVEL", {"0"}},
++ {"DRC MIN LEVEL", {"0"}},
++ {"DAC RAMP RATE", {"4"}},
++ {"AEC MODE", {"adc left, adc right"}},
++ {"ADC DATA TO DAC TEST MODE", {"disable"}},
++ {"MCLK INVERT", {"0"}},
++ {"BCLK INVERT", {"0"}},
++ {"MCLK SOURCE", {"from mclk pin"}},
++
++ {"DMIC MUX", {"DMIC DISABLE"}},
++ {"SDP OUT MUX", {"FROM ADC OUT"}},
++ {"DAC SDP SRC MUX", {"SELECT SDP LEFT DATA"}},
++
++};
++
++static struct audio_para_conf aux_mic_inpath_para_audio[] = {//¶ÔÓ¦ÓÚMic1rpÊäÈëͨµÀ
++
++ {"MIC PGA GAIN", {"10"}},
++ {"ADC SCALE", {"1"}},
++ {"DMIC TYPE", {"dmic at high level"}},
++ {"ADC RAMP RATE", {"4"}},
++ {"ADC SDP MUTE", {"0"}},
++ {"ADC INVERTED", {"0"}},
++ {"ADC SYNC", {"0"}},
++ {"ADC RAM CLR", {"0"}},
++ {"ADC VOLUME", {"191"}},
++ {"ALC ENABLE", {"0"}},
++ {"ALC AUTOMUTE TYPE", {"automute disabled"}},
++ {"ALC WIN SIZE", {"0"}},
++ {"ALC MAX LEVEL", {"0"}},
++ {"ALC MIN LEVEL", {"0"}},
++ {"ALC AUTOMUTE WINSIZE", {"0"}},
++ {"ALC AUTOMUTE GATE THRESHOLD", {"0"}},
++ {"ALC AUTOMUTE VOLUME", {"0"}},
++ {"ADC FS MODE", {"0"}},
++ {"DAC SDP MUTE", {"0"}},
++ {"DAC DEM MUTE", {"0"}},
++ {"DAC INVERT", {"0"}},
++ {"DAC RAM CLR", {"0"}},
++ {"DAC DSM MUTE", {"mute to 8"}},
++ {"DAC OFFSET", {"0"}},
++ {"DAC VOLUME", {"191"}},
++ {"DRC ENABLE", {"0"}},
++ {"DRC WIN SIZE", {"0"}},
++ {"DRC MAX LEVEL", {"0"}},
++ {"DRC MIN LEVEL", {"0"}},
++ {"DAC RAMP RATE", {"4"}},
++ {"AEC MODE", {"adc left, adc right"}},
++ {"ADC DATA TO DAC TEST MODE", {"disable"}},
++ {"MCLK INVERT", {"0"}},
++ {"BCLK INVERT", {"0"}},
++ {"MCLK SOURCE", {"from mclk pin"}},
++
++ {"DMIC MUX", {"DMIC DISABLE"}},
++ {"SDP OUT MUX", {"FROM ADC OUT"}},
++ {"DAC SDP SRC MUX", {"SELECT SDP LEFT DATA"}},
++
++
++
++};
++
++static struct audio_para_conf handset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++ {"MIC PGA GAIN", {"10"}},
++ {"ADC SCALE", {"1"}},
++ {"DMIC TYPE", {"dmic at high level"}},
++ {"ADC RAMP RATE", {"4"}},
++ {"ADC SDP MUTE", {"0"}},
++ {"ADC INVERTED", {"0"}},
++ {"ADC SYNC", {"0"}},
++ {"ADC RAM CLR", {"0"}},
++ {"ADC VOLUME", {"191"}},
++ {"ALC ENABLE", {"0"}},
++ {"ALC AUTOMUTE TYPE", {"automute disabled"}},
++ {"ALC WIN SIZE", {"0"}},
++ {"ALC MAX LEVEL", {"0"}},
++ {"ALC MIN LEVEL", {"0"}},
++ {"ALC AUTOMUTE WINSIZE", {"0"}},
++ {"ALC AUTOMUTE GATE THRESHOLD", {"0"}},
++ {"ALC AUTOMUTE VOLUME", {"0"}},
++ {"ADC FS MODE", {"0"}},
++ {"DAC SDP MUTE", {"0"}},
++ {"DAC DEM MUTE", {"0"}},
++ {"DAC INVERT", {"0"}},
++ {"DAC RAM CLR", {"0"}},
++ {"DAC DSM MUTE", {"mute to 8"}},
++ {"DAC OFFSET", {"0"}},
++ {"DAC VOLUME", {"191"}},
++ {"DRC ENABLE", {"0"}},
++ {"DRC WIN SIZE", {"0"}},
++ {"DRC MAX LEVEL", {"0"}},
++ {"DRC MIN LEVEL", {"0"}},
++ {"DAC RAMP RATE", {"4"}},
++ {"AEC MODE", {"adc left, adc right"}},
++ {"ADC DATA TO DAC TEST MODE", {"disable"}},
++ {"MCLK INVERT", {"0"}},
++ {"BCLK INVERT", {"0"}},
++ {"MCLK SOURCE", {"from mclk pin"}},
++
++ {"DMIC MUX", {"DMIC DISABLE"}},
++ {"SDP OUT MUX", {"FROM ADC OUT"}},
++ {"DAC SDP SRC MUX", {"SELECT SDP LEFT DATA"}},
++
++
++
++};
++
++static struct audio_para_conf headset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ Mic1rpÊäÈëͨµÀ
++ {"MIC PGA GAIN", {"10"}},
++ {"ADC SCALE", {"1"}},
++ {"DMIC TYPE", {"dmic at high level"}},
++ {"ADC RAMP RATE", {"4"}},
++ {"ADC SDP MUTE", {"0"}},
++ {"ADC INVERTED", {"0"}},
++ {"ADC SYNC", {"0"}},
++ {"ADC RAM CLR", {"0"}},
++ {"ADC VOLUME", {"191"}},
++ {"ALC ENABLE", {"0"}},
++ {"ALC AUTOMUTE TYPE", {"automute disabled"}},
++ {"ALC WIN SIZE", {"0"}},
++ {"ALC MAX LEVEL", {"0"}},
++ {"ALC MIN LEVEL", {"0"}},
++ {"ALC AUTOMUTE WINSIZE", {"0"}},
++ {"ALC AUTOMUTE GATE THRESHOLD", {"0"}},
++ {"ALC AUTOMUTE VOLUME", {"0"}},
++ {"ADC FS MODE", {"0"}},
++ {"DAC SDP MUTE", {"0"}},
++ {"DAC DEM MUTE", {"0"}},
++ {"DAC INVERT", {"0"}},
++ {"DAC RAM CLR", {"0"}},
++ {"DAC DSM MUTE", {"mute to 8"}},
++ {"DAC OFFSET", {"0"}},
++ {"DAC VOLUME", {"191"}},
++ {"DRC ENABLE", {"0"}},
++ {"DRC WIN SIZE", {"0"}},
++ {"DRC MAX LEVEL", {"0"}},
++ {"DRC MIN LEVEL", {"0"}},
++ {"DAC RAMP RATE", {"4"}},
++ {"AEC MODE", {"adc left, adc right"}},
++ {"ADC DATA TO DAC TEST MODE", {"disable"}},
++ {"MCLK INVERT", {"0"}},
++ {"BCLK INVERT", {"0"}},
++ {"MCLK SOURCE", {"from mclk pin"}},
++
++ {"DMIC MUX", {"DMIC DISABLE"}},
++ {"SDP OUT MUX", {"FROM ADC OUT"}},
++ {"DAC SDP SRC MUX", {"SELECT SDP LEFT DATA"}},
++};
++
++static struct audio_para_conf spk_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++
++ {"MIC PGA GAIN", {"10"}},
++ {"ADC SCALE", {"1"}},
++ {"DMIC TYPE", {"dmic at high level"}},
++ {"ADC RAMP RATE", {"4"}},
++ {"ADC SDP MUTE", {"0"}},
++ {"ADC INVERTED", {"0"}},
++ {"ADC SYNC", {"0"}},
++ {"ADC RAM CLR", {"0"}},
++ {"ADC VOLUME", {"191"}},
++ {"ALC ENABLE", {"0"}},
++ {"ALC AUTOMUTE TYPE", {"automute disabled"}},
++ {"ALC WIN SIZE", {"0"}},
++ {"ALC MAX LEVEL", {"0"}},
++ {"ALC MIN LEVEL", {"0"}},
++ {"ALC AUTOMUTE WINSIZE", {"0"}},
++ {"ALC AUTOMUTE GATE THRESHOLD", {"0"}},
++ {"ALC AUTOMUTE VOLUME", {"0"}},
++ {"ADC FS MODE", {"0"}},
++ {"DAC SDP MUTE", {"0"}},
++ {"DAC DEM MUTE", {"0"}},
++ {"DAC INVERT", {"0"}},
++ {"DAC RAM CLR", {"0"}},
++ {"DAC DSM MUTE", {"mute to 8"}},
++ {"DAC OFFSET", {"0"}},
++ {"DAC VOLUME", {"191"}},
++ {"DRC ENABLE", {"0"}},
++ {"DRC WIN SIZE", {"0"}},
++ {"DRC MAX LEVEL", {"0"}},
++ {"DRC MIN LEVEL", {"0"}},
++ {"DAC RAMP RATE", {"4"}},
++ {"AEC MODE", {"adc left, adc right"}},
++ {"ADC DATA TO DAC TEST MODE", {"disable"}},
++ {"MCLK INVERT", {"0"}},
++ {"BCLK INVERT", {"0"}},
++ {"MCLK SOURCE", {"from mclk pin"}},
++
++ {"DMIC MUX", {"DMIC DISABLE"}},
++ {"SDP OUT MUX", {"FROM ADC OUT"}},
++ {"DAC SDP SRC MUX", {"SELECT SDP LEFT DATA"}},
++};
++
++
++static struct audio_para_conf output_dac_vol = {
++ //"Playback Volume", {"255"}
++ {"DAC VOLUME", {"191"}},
++
++
++};
++
++static struct audio_para_conf input_adc_vol = {
++ //"Capture Volume", {"255"}
++ {"ADC VOLUME", {"191"}},
++
++};
++
++static struct audio_para_conf dac_mute = {
++ //"DAC MUTE", {"1"}
++ {"DAC SDP MUTE", {"0"}},
++ {"DAC DEM MUTE", {"0"}},
++
++
++};
++static struct audio_para_conf adc_mute = {
++ //"Input Boost Stage PGA Mute Switch", {"0"}
++ {"ADC SDP MUTE", {"0"}},
++
++
++};
++
++static struct audio_para_conf spk_path_onoff[] = {
++ //{"Mono Mixer PCM Playback Switch", {"0"}},
++ {"DAC SDP MUTE", {"0"}},
++ {"DAC DEM MUTE", {"0"}},
++
++
++};
++
++static struct audio_para_conf rcv_path_onoff[] = {
++ //{"Mono Mixer PCM Playback Switch", {"0"}},
++ {"ADC SDP MUTE", {"0"}},
++
++};
++
++static struct audio_para_conf earp_path_onoff[] = {
++ //{"Speaker Mixer PCM Playback Switch", {"0"}},
++ {"DAC SDP MUTE", {"0"}},
++ {"DAC DEM MUTE", {"0"}},
++};
++
++/* yu.dong@20240627 [T106BUG-615]CODEC 8311 using voice_demo to set codec volume has no effect start */
++
++/* yu.dong@20240716 [T106BUG-615]Abnormal whistling tone heard on the side of the phone when dialing in 3G network start */
++enum t_input_vol {
++ T_INPUT_VOL_MINUS_96DB = 0,
++ T_INPUT_VOL_MINUS_95DB = 2,
++ T_INPUT_VOL_MINUS_90DB = 12,
++ T_INPUT_VOL_MINUS_85DB = 22,
++ T_INPUT_VOL_MINUS_80DB = 32,
++ T_INPUT_VOL_MINUS_75DB = 42,
++ T_INPUT_VOL_MINUS_70DB = 52,
++ T_INPUT_VOL_MINUS_65DB = 62,
++ T_INPUT_VOL_MINUS_60DB = 72,
++ T_INPUT_VOL_MINUS_55DB = 82,
++ T_INPUT_VOL_MINUS_50DB = 92,
++ T_INPUT_VOL_MINUS_45DB = 102,
++ T_INPUT_VOL_MINUS_40DB = 112,
++ T_INPUT_VOL_MINUS_35DB = 122,
++ T_INPUT_VOL_MINUS_30DB = 132,
++ T_INPUT_VOL_MINUS_25DB = 142,
++ T_INPUT_VOL_MINUS_20DB = 152,
++ T_INPUT_VOL_MINUS_15DB = 162,
++ T_INPUT_VOL_MINUS_10DB = 172,
++ T_INPUT_VOL_MINUS_7DB = 178,
++ T_INPUT_VOL_MINUS_6DB = 180,
++ T_INPUT_VOL_MINUS_5DB = 182,
++ T_INPUT_VOL_MINUS_4DB = 184,
++ T_INPUT_VOL_MINUS_3DB = 186,
++ T_INPUT_VOL_MINUS_2DB = 188,
++ T_INPUT_VOL_MINUS_1DB = 190,
++ T_INPUT_VOL_0DB = 192
++};
++
++static int input_vol_conversion(int vol)
++{
++ switch(vol) {
++ case T_AUDIO_INPUT_VOL_LEVEL_0:
++ return T_INPUT_VOL_MINUS_96DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_1:
++ return T_INPUT_VOL_MINUS_30DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_2:
++ return T_INPUT_VOL_MINUS_25DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_3:
++ return T_INPUT_VOL_MINUS_20DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_4:
++ return T_INPUT_VOL_MINUS_15DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_5:
++ return T_INPUT_VOL_MINUS_10DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_6:
++ return T_INPUT_VOL_MINUS_7DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_7:
++ return T_INPUT_VOL_MINUS_4DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_8:
++ return T_INPUT_VOL_MINUS_3DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_9:
++ return T_INPUT_VOL_MINUS_2DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_10:
++ return T_INPUT_VOL_MINUS_1DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_11:
++ return T_INPUT_VOL_0DB;
++ default:
++ return T_INPUT_VOL_MINUS_30DB;
++ }
++}
++/* yu.dong@20240716 [T106BUG-615]Abnormal whistling tone heard on the side of the phone when dialing in 3G network end */
++
++enum t_output_vol {
++ T_OUTPUT_VOL_MINUS_96DB = 0,
++ T_OUTPUT_VOL_MINUS_95DB = 2,
++ T_OUTPUT_VOL_MINUS_90DB = 12,
++ T_OUTPUT_VOL_MINUS_85DB = 22,
++ T_OUTPUT_VOL_MINUS_80DB = 32,
++ T_OUTPUT_VOL_MINUS_75DB = 42,
++ T_OUTPUT_VOL_MINUS_70DB = 52,
++ T_OUTPUT_VOL_MINUS_65DB = 62,
++ T_OUTPUT_VOL_MINUS_60DB = 72,
++ T_OUTPUT_VOL_MINUS_55DB = 82,
++ T_OUTPUT_VOL_MINUS_50DB = 92,
++ T_OUTPUT_VOL_MINUS_45DB = 102,
++ T_OUTPUT_VOL_MINUS_40DB = 112,
++ T_OUTPUT_VOL_MINUS_35DB = 122,
++ T_OUTPUT_VOL_MINUS_30DB = 132,
++ T_OUTPUT_VOL_MINUS_25DB = 142,
++ T_OUTPUT_VOL_MINUS_20DB = 152,
++ T_OUTPUT_VOL_MINUS_15DB = 162,
++ T_OUTPUT_VOL_MINUS_10DB = 172,
++ T_OUTPUT_VOL_MINUS_7DB = 178,
++ T_OUTPUT_VOL_MINUS_6DB = 180,
++ T_OUTPUT_VOL_MINUS_5DB = 182,
++ T_OUTPUT_VOL_MINUS_4DB = 184,
++ T_OUTPUT_VOL_MINUS_3DB = 186,
++ T_OUTPUT_VOL_MINUS_2DB = 188,
++ T_OUTPUT_VOL_MINUS_1DB = 190,
++ T_OUTPUT_VOL_0DB = 192
++};
++
++ static int output_vol_conversion(int vol)
++{
++ switch(vol){
++ case T_AUDIO_OUTPUT_VOL_LEVEL_0:
++ return T_OUTPUT_VOL_MINUS_96DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_1:
++ return T_OUTPUT_VOL_MINUS_45DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_2:
++ return T_OUTPUT_VOL_MINUS_40DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_3:
++ return T_OUTPUT_VOL_MINUS_35DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_4:
++ return T_OUTPUT_VOL_MINUS_30DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_5:
++ return T_OUTPUT_VOL_MINUS_25DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_6:
++ return T_OUTPUT_VOL_MINUS_20DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_7:
++ return T_OUTPUT_VOL_MINUS_15DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_8:
++ return T_OUTPUT_VOL_MINUS_10DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_9:
++ return T_OUTPUT_VOL_MINUS_6DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_10:
++ return T_OUTPUT_VOL_MINUS_3DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_11:
++ return T_OUTPUT_VOL_0DB;
++ default:
++ return T_OUTPUT_VOL_0DB;
++ }
++}
++
++/* yu.dong@20240627 [T106BUG-615]CODEC 8311 using voice_demo to set codec volume has no effect end */
++
++//l.yang modify for bug id T106BUG-337 2023/11/9 start
++#elif defined _USE_CODEC_TI3104
++
++static struct audio_para_conf init_default_para[] = { //¿¿¿¿¿¿¿
++
++};
++
++static struct audio_para_conf common_out_para_audio[] = { //¿¿¿¿¿¿
++ //{"DAC Soft Mute Control", {"0"}},
++};
++
++
++static struct audio_para_conf common_in_para_audio[] = { //¿¿¿¿¿¿
++ //{"Mic Gain Control", {"0"}},
++};
++
++static struct audio_para_conf hp_outpath_para_audio[] = { //¿¿¿Hp¿¿¿¿
++ {"Line Playback Switch", {"1","1"}},
++ {"PCM Playback Volume", {"110","110"}},
++ {"Line Playback Volume", {"8","8"}},
++ {"Line DAC Playback Volume", {"110","110"}},
++};
++
++static struct audio_para_conf spk_outpath_para_audio[] = { //¿¿¿Spk¿¿¿¿
++ {"Line Playback Switch", {"1","1"}},
++ {"PCM Playback Volume", {"110","110"}},
++ {"Line Playback Volume", {"8","8"}},
++ {"Line DAC Playback Volume", {"110","110"}},
++};
++
++static struct audio_para_conf main_mic_inpath_para_audio[] = { //¿¿¿Mic1lp_Mic1lm¿¿¿¿
++ {"MicBias VG", {"1"}},
++ {"PGA Capture Volume", {"50","50"}}, //yu.dong@20240821 [AUDIO] Fix audio return tone problem on speakerphone
++ {"PGA Capture Switch", {"1","1"}},
++ {"ADC HPF Cut-off", {"1","1"}},
++
++ {"Left PGA Mixer Mic2L Switch",{"1"}},
++ {"Left PGA Mixer Mic2R Switch",{"1"}},
++ {"Right PGA Mixer Mic2L Switch",{"1"}},
++ {"Right PGA Mixer Mic2R Switch",{"1"}},
++};
++
++static struct audio_para_conf aux_mic_inpath_para_audio[] = {//¿¿¿Mic1rp¿¿¿¿
++ {"MicBias VG", {"1"}},
++ {"PGA Capture Volume", {"50","50"}}, //yu.dong@20240821 [AUDIO] Fix audio return tone problem on speakerphone
++ {"PGA Capture Switch", {"1","1"}},
++ {"ADC HPF Cut-off", {"1","1"}},
++
++ {"Left PGA Mixer Mic2L Switch",{"1"}},
++ {"Left PGA Mixer Mic2R Switch",{"1"}},
++ {"Right PGA Mixer Mic2L Switch",{"1"}},
++ {"Right PGA Mixer Mic2R Switch",{"1"}},
++};
++
++static struct audio_para_conf handset_inoutpath_para_voice[] = { //¿¿¿Hp¿¿¿¿Mic1lp_Mic1lm¿¿¿¿
++ //in
++ //#0x2d b6 pga mute
++ {"MicBias VG", {"1"}},
++ {"PGA Capture Volume", {"50","50"}}, //yu.dong@20240821 [AUDIO] Fix audio return tone problem on speakerphone
++ {"PGA Capture Switch", {"1","1"}},
++ {"ADC HPF Cut-off", {"1","1"}},
++
++ {"Left PGA Mixer Mic2L Switch",{"1"}},
++ {"Left PGA Mixer Mic2R Switch",{"1"}},
++ {"Right PGA Mixer Mic2L Switch",{"1"}},
++ {"Right PGA Mixer Mic2R Switch",{"1"}},
++
++ //out
++ {"Line Playback Switch", {"1","1"}},
++ {"PCM Playback Volume", {"110","110"}},
++ {"Line Playback Volume", {"8","8"}},
++ {"Line DAC Playback Volume", {"110","110"}},
++
++ //voice
++ #ifndef USE_CAP_SUPPORT
++ {"voice processing path select", {"handset"}}, // handset speak headset bluetooth
++ #endif
++};
++
++static struct audio_para_conf headset_inoutpath_para_voice[] = { //¿¿¿Hp¿¿¿¿ Mic1rp¿¿¿¿
++ //in
++ //#0x2d b6 pga mute
++ {"MicBias VG", {"1"}},
++ {"PGA Capture Volume", {"50","50"}}, //yu.dong@20240821 [AUDIO] Fix audio return tone problem on speakerphone
++ {"PGA Capture Switch", {"1","1"}},
++ {"ADC HPF Cut-off", {"1","1"}},
++
++ {"Left PGA Mixer Mic2L Switch",{"1"}},
++ {"Left PGA Mixer Mic2R Switch",{"1"}},
++ {"Right PGA Mixer Mic2L Switch",{"1"}},
++ {"Right PGA Mixer Mic2R Switch",{"1"}},
++
++ //out
++ {"Line Playback Switch", {"1","1"}},
++ {"PCM Playback Volume", {"110","110"}},
++ {"Line Playback Volume", {"8","8"}},
++ {"Line DAC Playback Volume", {"110","110"}},
++
++ //voice
++ #ifndef USE_CAP_SUPPORT
++ {"voice processing select", {"headset"}}, // handset speak headset bluetooth
++ #endif
++};
++
++static struct audio_para_conf spk_inoutpath_para_voice[] = { //¿¿¿Spk¿¿¿¿Mic1lp_Mic1lm¿¿¿¿
++ //in
++ //#0x2d b6 pga mute
++ {"MicBias VG", {"1"}},
++ {"PGA Capture Volume", {"50","50"}}, //yu.dong@20240821 [AUDIO] Fix audio return tone problem on speakerphone
++ {"PGA Capture Switch", {"1","1"}},
++ {"ADC HPF Cut-off", {"1","1"}},
++
++ {"Left PGA Mixer Mic2L Switch",{"1"}},
++ {"Left PGA Mixer Mic2R Switch",{"1"}},
++ {"Right PGA Mixer Mic2L Switch",{"1"}},
++ {"Right PGA Mixer Mic2R Switch",{"1"}},
++
++ //out
++ {"Line Playback Switch", {"1","1"}},
++ {"PCM Playback Volume", {"110","110"}},
++ {"Line Playback Volume", {"8","8"}},
++ {"Line DAC Playback Volume", {"110","110"}},
++ //voice
++
++ #ifndef USE_CAP_SUPPORT
++ {"voice processing path select", {"speak"}}, // handset speak headset bluetooth
++ #endif
++};
++
++static struct audio_para_conf output_dac_vol = {
++ {"PCM Playback Volume", {"110","110"}},
++};
++
++static struct audio_para_conf input_adc_vol = {
++ {"PGA Capture Volume", {"50","50"}}, //yu.dong@20240821 [AUDIO] Fix audio return tone problem on speakerphone
++};
++
++static struct audio_para_conf dac_mute = {
++ "Line Playback Switch", {"0","0"}
++};
++
++static struct audio_para_conf adc_mute = {
++ "MicBias VG", {"0"}
++};
++
++static struct audio_para_conf spk_path_onoff[] = {
++ {"Mono Mixer PCM Playback Switch", {"0"}},
++};
++
++static struct audio_para_conf rcv_path_onoff[] = {
++ {"Mono Mixer PCM Playback Switch", {"0"}},
++};
++
++static struct audio_para_conf earp_path_onoff[] = {
++ {"Speaker Mixer PCM Playback Switch", {"0"}},
++};
++
++static int output_vol_conversion(int vol)
++{
++ return 120;
++}
++
++static int input_vol_conversion(int vol)
++{
++ return 100;
++}
++//l.yang modify for bug id T106BUG-337 2023/11/9 end
++
++#elif defined _USE_CODEC_ES8374
++
++
++enum t_output_vol {
++ T_OUTPUT_VOL_MINUS_96DB = 0,
++ T_OUTPUT_VOL_MINUS_95DB = 2,
++ T_OUTPUT_VOL_MINUS_90DB = 12,
++ T_OUTPUT_VOL_MINUS_85DB = 22,
++ T_OUTPUT_VOL_MINUS_80DB = 32,
++ T_OUTPUT_VOL_MINUS_75DB = 42,
++ T_OUTPUT_VOL_MINUS_70DB = 52,
++ T_OUTPUT_VOL_MINUS_65DB = 62,
++ T_OUTPUT_VOL_MINUS_60DB = 72,
++ T_OUTPUT_VOL_MINUS_55DB = 82,
++ T_OUTPUT_VOL_MINUS_50DB = 92,
++ T_OUTPUT_VOL_MINUS_45DB = 102,
++ T_OUTPUT_VOL_MINUS_40DB = 112,
++ T_OUTPUT_VOL_MINUS_35DB = 122,
++ T_OUTPUT_VOL_MINUS_30DB = 132,
++ T_OUTPUT_VOL_MINUS_25DB = 142,
++ T_OUTPUT_VOL_MINUS_20DB = 152,
++ T_OUTPUT_VOL_MINUS_15DB = 162,
++ T_OUTPUT_VOL_MINUS_10DB = 172,
++ T_OUTPUT_VOL_MINUS_7DB = 178,
++ T_OUTPUT_VOL_MINUS_6DB = 180,
++ T_OUTPUT_VOL_MINUS_5DB = 182,
++ T_OUTPUT_VOL_MINUS_4DB = 184,
++ T_OUTPUT_VOL_MINUS_3DB = 186,
++ T_OUTPUT_VOL_MINUS_2DB = 188,
++ T_OUTPUT_VOL_MINUS_1DB = 190,
++ T_OUTPUT_VOL_0DB = 192
++};
++
++enum t_input_vol {
++ T_INPUT_VOL_MINUS_96DB = 0,
++ T_INPUT_VOL_MINUS_95DB = 2,
++ T_INPUT_VOL_MINUS_90DB = 12,
++ T_INPUT_VOL_MINUS_85DB = 22,
++ T_INPUT_VOL_MINUS_80DB = 32,
++ T_INPUT_VOL_MINUS_75DB = 42,
++ T_INPUT_VOL_MINUS_70DB = 52,
++ T_INPUT_VOL_MINUS_65DB = 62,
++ T_INPUT_VOL_MINUS_60DB = 72,
++ T_INPUT_VOL_MINUS_55DB = 82,
++ T_INPUT_VOL_MINUS_50DB = 92,
++ T_INPUT_VOL_MINUS_45DB = 102,
++ T_INPUT_VOL_MINUS_40DB = 112,
++ T_INPUT_VOL_MINUS_35DB = 122,
++ T_INPUT_VOL_MINUS_30DB = 132,
++ T_INPUT_VOL_MINUS_25DB = 142,
++ T_INPUT_VOL_MINUS_20DB = 152,
++ T_INPUT_VOL_MINUS_15DB = 162,
++ T_INPUT_VOL_MINUS_10DB = 172,
++ T_INPUT_VOL_MINUS_7DB = 178,
++ T_INPUT_VOL_MINUS_6DB = 180,
++ T_INPUT_VOL_MINUS_5DB = 182,
++ T_INPUT_VOL_MINUS_4DB = 184,
++ T_INPUT_VOL_MINUS_3DB = 186,
++ T_INPUT_VOL_MINUS_2DB = 188,
++ T_INPUT_VOL_MINUS_1DB = 190,
++ T_INPUT_VOL_0DB = 192
++};
++
++
++static struct audio_para_conf init_default_para[] = { //¿ª»ú³õʼ»¯µ÷ÓÃ
++ {"DMIC MUX", {"0"}},
++ {"SDP OUT MUX", {"0"}},
++ {"ALC MUX", {"0"}},
++ {"D2SE MIC BOOST GAIN", {"1"}},
++ {"LIN PGA GAIN", {"6"}},
++ {"ADC Capture Volume", {"192"}},
++ {"ALC Capture Max PGA", {"15"}},
++ {"DAC MUTE", {"0"}},
++ {"DAC Playback Volume", {"120"}},
++ {"DAC SDP SRC MUX", {"0"}},
++ {"DAC SRC MUX", {"0"}}
++};
++
++//#ifdef _USE_7520V3_PHONE_TYPE_C31F
++#if ( defined _USE_7520V3_PHONE_TYPE_C31F || defined _USE_7520V3_PHONE_TYPE_WTWD )
++
++static struct audio_para_conf common_out_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ {"DAC MUTE", {"0"}},
++ //{"DAC Playback Volume", {"120"}},
++ {"DAC SDP SRC MUX", {"0"}},
++ {"DAC SRC MUX", {"0"}}
++};
++
++static struct audio_para_conf common_in_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ {"DMIC MUX", {"0"}},
++ {"SDP OUT MUX", {"0"}},
++ {"ADC Soft Ramp", {"0"}},
++ {"ADC HPF COEFFICIENT", {"5"}},
++#if 0
++ {"ALC MUX", {"1"}},
++ {"ALC Capture Target Volume", {"5"}},
++ {"ALC Capture Max PGA", {"11"}},
++ {"ALC Capture Min PGA", {"2"}},
++ {"ALC Capture Hold Time", {"0"}},
++ {"ALC Capture Decay Time", {"0"}},
++ {"ALC Capture Attack Time", {"0"}},
++ {"ALC WIN SIZE", {"6"}},
++ {"ALC Capture NG Threshold", {"14"}},
++ {"ALC Capture NG Type", {"0"}},
++ {"ALC Capture NG Switch", {"0"}},
++#endif
++ {"D2SE MIC BOOST GAIN", {"1"}},
++ {"LIN PGA GAIN", {"6"}},
++ {"ADC Capture Volume", {"192"}},
++};
++
++#ifdef _USE_7520V3_PHONE_TYPE_WTWD
++static struct audio_para_conf hp_outpath_para_audio[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ
++ {"MONO MIXER DAC TO MONO OUT Switch", {"0"}},
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"1"}},
++ {"SPEAKER MIXER GAIN", {"41"}}, //1d
++ {"SPEAKER OUTPUT Volume", {"0"}}, //1e
++ {"DAC Playback Volume", {"192"}}, //38
++};
++#else
++static struct audio_para_conf hp_outpath_para_audio[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"0"}},
++ {"MONO OUT GAIN", {"4"}},
++ {"MONO MIXER DAC TO MONO OUT Switch", {"1"}},
++ {"audio path select",{"handset"}},
++};
++
++#endif
++/*
++static struct audio_para_conf spk_outpath_para_audio[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀ
++ {"MONO MIXER DAC TO MONO OUT Switch", {"0"}},
++ {"SPEAKER MIXER GAIN", {"4"}},
++ {"SPEAKER OUTPUT Volume", {"4"}},
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"1"}}
++};
++*/
++
++static struct audio_para_conf spk_outpath_para_audio[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀ
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"0"}},
++ {"MONO OUT GAIN", {"11"}},
++ {"MONO MIXER DAC TO MONO OUT Switch", {"1"}},
++ {"audio path select",{"speak"}},
++};
++
++static struct audio_para_conf main_mic_inpath_para_audio[] = { //¶ÔÓ¦ÓÚLin1-Rin1ÊäÈëͨµÀ
++ {"DIFFERENTIAL MUX", {"1"}},
++};
++
++static struct audio_para_conf aux_mic_inpath_para_audio[] = {//¶ÔÓ¦ÓÚLin2-Rin2ÊäÈëͨµÀ
++ {"DIFFERENTIAL MUX", {"2"}},
++};
++
++#ifdef _USE_7520V3_PHONE_TYPE_WTWD
++
++static struct audio_para_conf handset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++#ifndef USE_CAP_SUPPORT
++
++ //{"voice processing path select", {"headset"}}, // handset speak headset bluetooth
++ {"voice processing path select", {"handset"}}, // handset speak headset bluetooth
++#endif
++ {"DIFFERENTIAL MUX", {"1"}},
++ {"DMIC MUX", {"0"}},
++ {"SDP OUT MUX", {"0"}},
++ {"ADC Soft Ramp", {"0"}},
++ {"ADC HPF COEFFICIENT", {"5"}},
++
++ {"ALC MUX", {"0"}},
++ {"D2SE MIC BOOST GAIN", {"1"}},
++ {"LIN PGA GAIN", {"6"}},
++ {"ADC Capture Volume", {"192"}},
++
++ {"MONO MIXER DAC TO MONO OUT Switch", {"0"}},
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"1"}},
++ {"SPEAKER MIXER GAIN", {"32"}}, //old 41
++ {"SPEAKER OUTPUT Volume", {"0"}}, //1
++ {"DAC Playback Volume", {"192"}}, //38
++};
++
++#else
++static struct audio_para_conf handset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++#ifndef USE_CAP_SUPPORT
++
++ {"voice processing path select", {"handset"}}, // handset speak headset bluetooth
++#endif
++ {"DIFFERENTIAL MUX", {"1"}},
++ {"DMIC MUX", {"0"}},
++ {"SDP OUT MUX", {"0"}},
++ {"ADC Soft Ramp", {"0"}},
++ {"ADC HPF COEFFICIENT", {"5"}},
++
++ {"ALC MUX", {"0"}},
++#if 0
++ {"ALC Capture Target Volume", {"7"}},
++ {"ALC Capture Max PGA", {"13"}},
++ {"ALC Capture Min PGA", {"8"}},
++ {"ALC Capture Hold Time", {"0"}},
++ {"ALC Capture Decay Time", {"1"}},
++ {"ALC Capture Attack Time", {"2"}},
++ {"ALC WIN SIZE", {"6"}},
++ {"ALC Capture NG Threshold", {"14"}},
++ {"ALC Capture NG Type", {"0"}},
++ {"ALC Capture NG Switch", {"0"}},
++#endif
++ {"D2SE MIC BOOST GAIN", {"1"}},
++ {"LIN PGA GAIN", {"6"}},
++ {"ADC Capture Volume", {"192"}},
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"0"}},
++ {"MONO OUT GAIN", {"11"}},
++ {"DAC Playback Volume", {"192"}},
++ {"MONO MIXER DAC TO MONO OUT Switch", {"1"}},
++};
++#endif
++static struct audio_para_conf headset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ Mic1rpÊäÈëͨµÀ
++ {"DIFFERENTIAL MUX", {"1"}},
++ {"DMIC MUX", {"0"}},
++ {"SDP OUT MUX", {"0"}},
++ {"ADC Soft Ramp", {"0"}},
++ {"ADC HPF COEFFICIENT", {"5"}},
++
++ {"ALC MUX", {"0"}},
++#if 0
++ {"ALC Capture Target Volume", {"7"}},
++ {"ALC Capture Max PGA", {"13"}},
++ {"ALC Capture Min PGA", {"8"}},
++ {"ALC Capture Hold Time", {"0"}},
++ {"ALC Capture Decay Time", {"1"}},
++ {"ALC Capture Attack Time", {"2"}},
++ {"ALC WIN SIZE", {"6"}},
++ {"ALC Capture NG Threshold", {"14"}},
++ {"ALC Capture NG Type", {"0"}},
++ {"ALC Capture NG Switch", {"0"}},
++#endif
++ {"D2SE MIC BOOST GAIN", {"1"}},
++ {"LIN PGA GAIN", {"7"}},
++ {"ADC Capture Volume", {"192"}},
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"0"}},
++ {"MONO OUT GAIN", {"4"}},
++ {"DAC Playback Volume", {"190"}},
++ {"MONO MIXER DAC TO MONO OUT Switch", {"1"}},
++#ifndef USE_CAP_SUPPORT
++ {"voice processing path select", {"headset"}}, // handset speak headset bluetooth
++#endif
++};
++#ifdef _USE_7520V3_PHONE_TYPE_WTWD //class-d -->receiver
++static struct audio_para_conf spk_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++ {"DIFFERENTIAL MUX", {"1"}},
++ {"DMIC MUX", {"0"}},
++ {"SDP OUT MUX", {"0"}},
++ {"ADC Soft Ramp", {"0"}},
++ {"ADC HPF COEFFICIENT", {"5"}},
++
++ {"ALC MUX", {"0"}},
++#if 0
++ {"ALC Capture Target Volume", {"7"}},
++ {"ALC Capture Max PGA", {"13"}},
++ {"ALC Capture Min PGA", {"8"}},
++ {"ALC Capture Hold Time", {"0"}},
++ {"ALC Capture Decay Time", {"1"}},
++ {"ALC Capture Attack Time", {"2"}},
++ {"ALC WIN SIZE", {"6"}},
++ {"ALC Capture NG Threshold", {"14"}},
++ {"ALC Capture NG Type", {"0"}},
++ {"ALC Capture NG Switch", {"0"}},
++#endif
++ {"D2SE MIC BOOST GAIN", {"1"}},
++ {"LIN PGA GAIN", {"6"}},
++ {"ADC Capture Volume", {"192"}},
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"0"}},
++ {"MONO OUT GAIN", {"4"}},
++ {"DAC Playback Volume", {"186"}},
++ {"MONO MIXER DAC TO MONO OUT Switch", {"1"}},
++#ifndef USE_CAP_SUPPORT
++ {"voice processing path select", {"speak"}}, // handset speak headset bluetooth
++#endif
++};
++#else//momo out -> speaker
++static struct audio_para_conf spk_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++ {"DIFFERENTIAL MUX", {"1"}},
++ {"DMIC MUX", {"0"}},
++ {"SDP OUT MUX", {"0"}},
++ {"ADC Soft Ramp", {"0"}},
++ {"ADC HPF COEFFICIENT", {"5"}},
++
++ {"ALC MUX", {"0"}},
++#if 0
++ {"ALC Capture Target Volume", {"7"}},
++ {"ALC Capture Max PGA", {"13"}},
++ {"ALC Capture Min PGA", {"8"}},
++ {"ALC Capture Hold Time", {"0"}},
++ {"ALC Capture Decay Time", {"1"}},
++ {"ALC Capture Attack Time", {"2"}},
++ {"ALC WIN SIZE", {"6"}},
++ {"ALC Capture NG Threshold", {"14"}},
++ {"ALC Capture NG Type", {"0"}},
++ {"ALC Capture NG Switch", {"0"}},
++#endif
++ {"D2SE MIC BOOST GAIN", {"1"}},
++ {"LIN PGA GAIN", {"6"}},
++ {"ADC Capture Volume", {"192"}},
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"0"}},
++ {"MONO OUT GAIN", {"0"}},
++ {"DAC Playback Volume", {"186"}},
++ {"MONO MIXER DAC TO MONO OUT Switch", {"1"}},
++#ifndef USE_CAP_SUPPORT
++ {"voice processing path select", {"speak"}}, // handset speak headset bluetooth
++#endif
++};
++
++#endif
++
++
++
++#else
++static struct audio_para_conf common_out_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ {"DAC MUTE", {"0"}},
++ //{"DAC Playback Volume", {"120"}},
++ {"DAC SDP SRC MUX", {"0"}},
++ {"DAC SRC MUX", {"0"}}
++};
++
++static struct audio_para_conf common_in_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ {"DMIC MUX", {"0"}},
++ {"SDP OUT MUX", {"0"}},
++ {"ADC Soft Ramp", {"0"}},
++ {"ADC HPF COEFFICIENT", {"5"}},
++#if 1
++ {"ALC MUX", {"1"}},
++ {"ALC Capture Target Volume", {"5"}},
++ {"ALC Capture Max PGA", {"11"}},
++ {"ALC Capture Min PGA", {"2"}},
++ {"ALC Capture Hold Time", {"0"}},
++ {"ALC Capture Decay Time", {"0"}},
++ {"ALC Capture Attack Time", {"0"}},
++ {"ALC WIN SIZE", {"6"}},
++ {"ALC Capture NG Threshold", {"14"}},
++ {"ALC Capture NG Type", {"0"}},
++ {"ALC Capture NG Switch", {"0"}},
++#endif
++ {"D2SE MIC BOOST GAIN", {"1"}},
++ {"LIN PGA GAIN", {"3"}},
++ {"ADC Capture Volume", {"180"}},
++};
++
++static struct audio_para_conf hp_outpath_para_audio[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"0"}},
++ {"MONO OUT GAIN", {"4"}},
++ {"MONO MIXER DAC TO MONO OUT Switch", {"1"}}
++};
++
++/*
++static struct audio_para_conf spk_outpath_para_audio[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀ
++ {"MONO MIXER DAC TO MONO OUT Switch", {"0"}},
++ {"SPEAKER MIXER GAIN", {"4"}},
++ {"SPEAKER OUTPUT Volume", {"4"}},
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"1"}}
++};
++*/
++
++static struct audio_para_conf spk_outpath_para_audio[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀ
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"0"}},
++ {"MONO OUT GAIN", {"3"}},
++ {"MONO MIXER DAC TO MONO OUT Switch", {"1"}}
++};
++
++static struct audio_para_conf main_mic_inpath_para_audio[] = { //¶ÔÓ¦ÓÚLin1-Rin1ÊäÈëͨµÀ
++ {"DIFFERENTIAL MUX", {"1"}},
++};
++
++static struct audio_para_conf aux_mic_inpath_para_audio[] = {//¶ÔÓ¦ÓÚLin2-Rin2ÊäÈëͨµÀ
++ {"DIFFERENTIAL MUX", {"2"}},
++};
++
++static struct audio_para_conf handset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++ {"DIFFERENTIAL MUX", {"1"}},
++ {"DMIC MUX", {"0"}},
++ {"SDP OUT MUX", {"0"}},
++ {"ADC Soft Ramp", {"0"}},
++ {"ADC HPF COEFFICIENT", {"5"}},
++
++ {"ALC MUX", {"0"}},
++#if 0
++ {"ALC Capture Target Volume", {"7"}},
++ {"ALC Capture Max PGA", {"13"}},
++ {"ALC Capture Min PGA", {"8"}},
++ {"ALC Capture Hold Time", {"0"}},
++ {"ALC Capture Decay Time", {"1"}},
++ {"ALC Capture Attack Time", {"2"}},
++ {"ALC WIN SIZE", {"6"}},
++ {"ALC Capture NG Threshold", {"14"}},
++ {"ALC Capture NG Type", {"0"}},
++ {"ALC Capture NG Switch", {"0"}},
++#endif
++ {"D2SE MIC BOOST GAIN", {"1"}},
++ {"LIN PGA GAIN", {"7"}},
++ {"ADC Capture Volume", {"192"}},
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"0"}},
++ {"MONO OUT GAIN", {"4"}},
++ {"DAC Playback Volume", {"190"}},
++ {"MONO MIXER DAC TO MONO OUT Switch", {"1"}},
++#ifndef USE_CAP_SUPPORT
++ {"voice processing path select", {"handset"}}, // handset speak headset bluetooth
++#endif
++};
++
++static struct audio_para_conf headset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ Mic1rpÊäÈëͨµÀ
++ {"DIFFERENTIAL MUX", {"1"}},
++ {"DMIC MUX", {"0"}},
++ {"SDP OUT MUX", {"0"}},
++ {"ADC Soft Ramp", {"0"}},
++ {"ADC HPF COEFFICIENT", {"5"}},
++
++ {"ALC MUX", {"0"}},
++#if 0
++ {"ALC Capture Target Volume", {"7"}},
++ {"ALC Capture Max PGA", {"13"}},
++ {"ALC Capture Min PGA", {"8"}},
++ {"ALC Capture Hold Time", {"0"}},
++ {"ALC Capture Decay Time", {"1"}},
++ {"ALC Capture Attack Time", {"2"}},
++ {"ALC WIN SIZE", {"6"}},
++ {"ALC Capture NG Threshold", {"14"}},
++ {"ALC Capture NG Type", {"0"}},
++ {"ALC Capture NG Switch", {"0"}},
++#endif
++ {"D2SE MIC BOOST GAIN", {"1"}},
++ {"LIN PGA GAIN", {"7"}},
++ {"ADC Capture Volume", {"192"}},
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"0"}},
++ {"MONO OUT GAIN", {"4"}},
++ {"DAC Playback Volume", {"190"}},
++ {"MONO MIXER DAC TO MONO OUT Switch", {"1"}},
++#ifndef USE_CAP_SUPPORT
++ {"voice processing path select", {"headset"}}, // handset speak headset bluetooth
++#endif
++};
++
++static struct audio_para_conf spk_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++ {"DIFFERENTIAL MUX", {"1"}},
++ {"DMIC MUX", {"0"}},
++ {"SDP OUT MUX", {"0"}},
++ {"ADC Soft Ramp", {"0"}},
++ {"ADC HPF COEFFICIENT", {"5"}},
++
++ {"ALC MUX", {"0"}},
++#if 0
++ {"ALC Capture Target Volume", {"7"}},
++ {"ALC Capture Max PGA", {"13"}},
++ {"ALC Capture Min PGA", {"8"}},
++ {"ALC Capture Hold Time", {"0"}},
++ {"ALC Capture Decay Time", {"1"}},
++ {"ALC Capture Attack Time", {"2"}},
++ {"ALC WIN SIZE", {"6"}},
++ {"ALC Capture NG Threshold", {"14"}},
++ {"ALC Capture NG Type", {"0"}},
++ {"ALC Capture NG Switch", {"0"}},
++#endif
++ {"D2SE MIC BOOST GAIN", {"1"}},
++ {"LIN PGA GAIN", {"7"}},
++ {"ADC Capture Volume", {"192"}},
++ {"SPEAKER MIXER DAC TO SPEAKER OUT Switch", {"0"}},
++ {"MONO OUT GAIN", {"4"}},
++ {"DAC Playback Volume", {"190"}},
++ {"MONO MIXER DAC TO MONO OUT Switch", {"1"}},
++#ifndef USE_CAP_SUPPORT
++ {"voice processing path select", {"speak"}}, // handset speak headset bluetooth
++#endif
++};
++
++#endif
++
++static struct audio_para_conf output_dac_vol = {"DAC Playback Volume", {"120"}};
++
++static struct audio_para_conf input_adc_vol = {"ADC Capture Volume", {"192"}};
++
++static struct audio_para_conf dac_mute = {"DAC MUTE", {"1"}};
++static struct audio_para_conf adc_mute = {"ADC MUTE", {"1"}};
++
++static struct audio_para_conf spk_path_onoff[] = {
++ {"MONO MIXER DAC TO MONO OUT Switch", {"0"}},
++};
++
++static struct audio_para_conf rcv_path_onoff[] = {
++ {"MONO MIXER DAC TO MONO OUT Switch", {"0"}},
++};
++
++static struct audio_para_conf earp_path_onoff[] = {
++ {"MONO MIXER DAC TO MONO OUT Switch", {"0"}},
++};
++
++
++static int output_vol_conversion(int vol)
++{
++ switch(vol){
++ case T_AUDIO_OUTPUT_VOL_LEVEL_0:
++ return T_OUTPUT_VOL_MINUS_96DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_1:
++ return T_OUTPUT_VOL_MINUS_45DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_2:
++ return T_OUTPUT_VOL_MINUS_40DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_3:
++ return T_OUTPUT_VOL_MINUS_35DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_4:
++ return T_OUTPUT_VOL_MINUS_30DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_5:
++ return T_OUTPUT_VOL_MINUS_25DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_6:
++ return T_OUTPUT_VOL_MINUS_20DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_7:
++ return T_OUTPUT_VOL_MINUS_15DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_8:
++ return T_OUTPUT_VOL_MINUS_10DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_9:
++ return T_OUTPUT_VOL_MINUS_6DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_10:
++ return T_OUTPUT_VOL_MINUS_3DB;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_11:
++ return T_OUTPUT_VOL_0DB;
++ default:
++ return T_OUTPUT_VOL_0DB;
++ }
++}
++
++static int input_vol_conversion(int vol)
++{
++ switch(vol) {
++ case T_AUDIO_INPUT_VOL_LEVEL_0:
++ return T_INPUT_VOL_MINUS_96DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_1:
++ return T_INPUT_VOL_MINUS_30DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_2:
++ return T_INPUT_VOL_MINUS_25DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_3:
++ return T_INPUT_VOL_MINUS_20DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_4:
++ return T_INPUT_VOL_MINUS_15DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_5:
++ return T_INPUT_VOL_MINUS_10DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_6:
++ return T_INPUT_VOL_MINUS_7DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_7:
++ return T_INPUT_VOL_MINUS_4DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_8:
++ return T_INPUT_VOL_MINUS_3DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_9:
++ return T_INPUT_VOL_MINUS_2DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_10:
++ return T_INPUT_VOL_MINUS_1DB;
++ case T_AUDIO_INPUT_VOL_LEVEL_11:
++ return T_INPUT_VOL_0DB;
++ default:
++ return T_INPUT_VOL_MINUS_30DB;
++ }
++}
++
++#elif defined _USE_CODEC_AK4940
++
++static struct audio_para_conf common_out_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ {"DAC Soft Mute Control", {"0"}},
++ //{"BICK Frequency", {"32fs"}},
++ {"BICK Frequency", {"2"}},//0 64fs,1 48fs,2 32fs
++
++};
++
++
++static struct audio_para_conf common_in_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++
++ {"Mic Gain Control", {"0"}},
++ {"ADC Digital Volume (VOLAD)", {"195"}},
++ {"ADC Soft Mute Control", {"0"}},
++
++
++};
++
++static struct audio_para_conf hp_outpath_para_audio[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ
++ {"OUT2 MUX", {"DAC"}},
++ {"Lineout Type", {"Single-end"}},
++
++};
++
++static struct audio_para_conf spk_outpath_para_audio[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀ
++ {"OUT1 MUX", {"DAC"}},
++ {"Lineout Type", {"Differential"}},
++
++};
++
++static struct audio_para_conf main_mic_inpath_para_audio[] = { //¶ÔÓ¦ÓÚMic1lp_Mic1lmÊäÈëͨµÀ
++
++ {"ADC Input Type", {"Single-end"}},
++ {"AIN MUX", {"AIN1"}},
++
++};
++
++static struct audio_para_conf aux_mic_inpath_para_audio[] = {//¶ÔÓ¦ÓÚMic1rpÊäÈëͨµÀ
++
++ {"ADC Input Type", {"Single-end"}},
++ {"AIN MUX", {"AIN2"}},
++};
++
++static struct audio_para_conf handset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++ // common in
++
++ {"Mic Gain Control", {"0"}},
++ {"ADC Digital Volume (VOLAD)", {"195"}},
++ {"ADC Soft Mute Control", {"0"}},
++ //diff in
++ {"ADC Input Type", {"Single-end"}},
++ {"AIN MUX", {"AIN1"}},
++
++ // common out
++
++ {"DAC Soft Mute Control", {"0"}},
++ //{"BICK Frequency", {"32fs"}},
++ {"BICK Frequency", {"2"}},//0 64fs,1 48fs,2 32fs
++ //diff out
++
++ //voice
++#ifndef USE_CAP_SUPPORT
++
++ {"voice processing path select", {"handset"}}, // handset speak headset bluetooth
++#endif
++};
++
++static struct audio_para_conf headset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ Mic1rpÊäÈëͨµÀ
++ // common in
++
++ {"Mic Gain Control", {"0"}},
++ {"ADC Digital Volume (VOLAD)", {"195"}},
++ {"ADC Soft Mute Control", {"0"}},
++ //diff in
++ {"ADC Input Type", {"Single-end"}},
++ {"AIN MUX", {"AIN2"}},
++ // common out
++
++ {"DAC Soft Mute Control", {"0"}},
++ //{"BICK Frequency", {"32fs"}},
++ {"BICK Frequency", {"2"}},//0 64fs,1 48fs,2 32fs
++ //diff out
++
++ {"OUT2 MUX", {"DAC"}},
++ {"Lineout Type", {"Single-end"}},
++ //voice
++#ifndef USE_CAP_SUPPORT
++
++ {"voice processing path select", {"headset"}}, // handset speak headset bluetooth
++#endif
++};
++
++static struct audio_para_conf spk_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++
++ // common in
++ {"Mic Gain Control", {"0"}},
++ {"ADC Digital Volume (VOLAD)", {"195"}},
++ {"ADC Soft Mute Control", {"0"}},
++ //diff in
++ {"ADC Input Type", {"Single-end"}},
++ {"AIN MUX", {"AIN1"}},
++ // common out
++ {"DAC Soft Mute Control", {"0"}},
++ //{"BICK Frequency", {"32fs"}},
++ {"BICK Frequency", {"2"}},//0 64fs,1 48fs,2 32fs
++ //diff out
++ {"OUT1 MUX", {"DAC"}},
++ {"Lineout Type", {"Differential"}},
++ //voice
++#ifndef USE_CAP_SUPPORT
++
++ {"voice processing path select", {"speak"}}, // handset speak headset bluetooth
++#endif
++};
++
++#elif defined _USE_CODEC_NAU8810
++static struct audio_para_conf init_default_para[] = { //¿ª»ú³õʼ»¯µ÷ÓÃ
++
++};
++
++static struct audio_para_conf common_out_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++ //{"DAC Soft Mute Control", {"0"}},
++
++
++};
++
++
++static struct audio_para_conf common_in_para_audio[] = { //¶ÔÓ¦¹«¹²²¿·Ö
++
++ //{"Mic Gain Control", {"0"}},
++
++};
++
++static struct audio_para_conf hp_outpath_para_audio[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ
++ {"Speaker Mute Switch", {"1"}},
++ {"Speaker Mixer PCM Playback Switch", {"0"}},
++ {"Mono Mute Switch", {"0"}},
++ {"Mono Mixer PCM Playback Switch", {"1"}},
++
++
++};
++
++static struct audio_para_conf spk_outpath_para_audio[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀ
++ {"Mono Mute Switch", {"1"}},
++ {"Mono Mixer PCM Playback Switch", {"0"}},
++ {"Speaker Volume", {"57"}},
++ {"Speaker Mute Switch", {"0"}},
++ {"Speaker Mixer PCM Playback Switch", {"1"}},
++
++
++};
++
++static struct audio_para_conf main_mic_inpath_para_audio[] = { //¶ÔÓ¦ÓÚMic1lp_Mic1lmÊäÈëͨµÀ
++
++ //#0x2d b6 pga mute
++ {"Input Boost Stage PGA Mute Switch", {"1"}},
++ {"Capture Volume", {"255"}},
++ {"PGA Volume", {"32"}},
++ {"Input PGA MicN Switch", {"1"}},
++ {"Input PGA MicP Switch", {"1"}},
++
++ //#0x2f b4~b6
++ {"Input Boost Stage PMIC PGA Switch", {"0"}},
++
++};
++
++static struct audio_para_conf aux_mic_inpath_para_audio[] = {//¶ÔÓ¦ÓÚMic1rpÊäÈëͨµÀ
++
++ //#0x2d b6 pga mute
++ {"Input Boost Stage PGA Mute Switch", {"1"}},
++ {"Capture Volume", {"255"}},
++ {"PGA Volume", {"32"}},
++ {"Input PGA MicN Switch", {"1"}},
++ {"Input PGA MicP Switch", {"1"}},
++
++ //#0x2f b4~b6
++ {"Input Boost Stage PMIC PGA Switch", {"0"}},
++
++
++};
++
++static struct audio_para_conf handset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++ //in
++ //#0x2d b6 pga mute
++ {"Input Boost Stage PGA Mute Switch", {"1"}},
++ {"Capture Volume", {"255"}},
++ {"PGA Volume", {"32"}},
++ {"Input PGA MicN Switch", {"1"}},
++ {"Input PGA MicP Switch", {"1"}},
++
++ //#0x2f b4~b6
++ {"Input Boost Stage PMIC PGA Switch", {"0"}},
++
++ //out
++ {"Playback Volume", {"255"}},
++ {"Speaker Mute Switch", {"1"}},
++ {"Speaker Mixer PCM Playback Switch", {"0"}},
++ {"Mono Mute Switch", {"0"}},
++ {"Mono Mixer PCM Playback Switch", {"1"}},
++
++
++
++ //voice
++#ifndef USE_CAP_SUPPORT
++
++ {"voice processing path select", {"handset"}}, // handset speak headset bluetooth
++#endif
++};
++
++static struct audio_para_conf headset_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚHpÊä³öͨµÀ Mic1rpÊäÈëͨµÀ
++ //in
++ //#0x2d b6 pga mute
++ {"Input Boost Stage PGA Mute Switch", {"1"}},
++ {"Capture Volume", {"255"}},
++ {"PGA Volume", {"32"}},
++ {"Input PGA MicN Switch", {"1"}},
++ {"Input PGA MicP Switch", {"1"}},
++
++ //#0x2f b4~b6
++ {"Input Boost Stage PMIC PGA Switch", {"0"}},
++
++ //out
++ {"Playback Volume", {"255"}},
++ {"Speaker Mute Switch", {"1"}},
++ {"Speaker Mixer PCM Playback Switch", {"0"}},
++ {"Mono Mute Switch", {"0"}},
++ {"Mono Mixer PCM Playback Switch", {"1"}},
++
++ //voice
++#ifndef USE_CAP_SUPPORT
++
++ {"voice processing path select", {"headset"}}, // handset speak headset bluetooth
++#endif
++};
++
++static struct audio_para_conf spk_inoutpath_para_voice[] = { //¶ÔÓ¦ÓÚSpkÊä³öͨµÀMic1lp_Mic1lmÊäÈëͨµÀ
++
++ //in
++ //#0x2d b6 pga mute
++ {"Input Boost Stage PGA Mute Switch", {"1"}},
++ {"Capture Volume", {"255"}},
++ {"PGA Volume", {"32"}},
++ {"Input PGA MicN Switch", {"1"}},
++ {"Input PGA MicP Switch", {"1"}},
++
++ //#0x2f b4~b6
++ {"Input Boost Stage PMIC PGA Switch", {"0"}},
++
++ //out
++ {"Playback Volume", {"255"}},
++ {"Mono Mute Switch", {"1"}},
++ {"Mono Mixer PCM Playback Switch", {"0"}},
++ {"Speaker Volume", {"63"}},
++ {"Speaker Mute Switch", {"0"}},
++ {"Speaker Mixer PCM Playback Switch", {"1"}},
++
++
++ //voice
++#ifndef USE_CAP_SUPPORT
++
++ {"voice processing path select", {"speak"}}, // handset speak headset bluetooth
++#endif
++};
++
++
++static struct audio_para_conf output_dac_vol = {
++ "Playback Volume", {"255"}
++
++};
++
++static struct audio_para_conf input_adc_vol = {
++ "Capture Volume", {"255"}
++};
++
++static struct audio_para_conf dac_mute = {
++ "DAC MUTE", {"1"}
++};
++static struct audio_para_conf adc_mute = {
++ "Input Boost Stage PGA Mute Switch", {"0"}
++};
++
++static struct audio_para_conf spk_path_onoff[] = {
++ {"Mono Mixer PCM Playback Switch", {"0"}},
++};
++
++static struct audio_para_conf rcv_path_onoff[] = {
++ {"Mono Mixer PCM Playback Switch", {"0"}},
++};
++
++static struct audio_para_conf earp_path_onoff[] = {
++ {"Speaker Mixer PCM Playback Switch", {"0"}},
++};
++
++
++static int output_vol_conversion(int vol)//reg 0xb
++{
++ switch(vol){
++ case T_AUDIO_OUTPUT_VOL_LEVEL_0:
++ return 189;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_1:
++ return 195;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_2:
++ return 201;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_3:
++ return 207;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_4:
++ return 213;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_5:
++ return 219;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_6:
++ return 225;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_7:
++ return 231;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_8:
++ return 237;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_9:
++ return 243;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_10:
++ return 249;
++ case T_AUDIO_OUTPUT_VOL_LEVEL_11:
++ return 255;
++ default:
++ return 255;
++ }
++}
++static int input_vol_conversion(int vol)//reg 0xf
++{
++ switch(vol) {
++ case T_AUDIO_INPUT_VOL_LEVEL_0:
++ return 189;
++ case T_AUDIO_INPUT_VOL_LEVEL_1:
++ return 195;
++ case T_AUDIO_INPUT_VOL_LEVEL_2:
++ return 201;
++ case T_AUDIO_INPUT_VOL_LEVEL_3:
++ return 207;
++ case T_AUDIO_INPUT_VOL_LEVEL_4:
++ return 213;
++ case T_AUDIO_INPUT_VOL_LEVEL_5:
++ return 219;
++ case T_AUDIO_INPUT_VOL_LEVEL_6:
++ return 225;
++ case T_AUDIO_INPUT_VOL_LEVEL_7:
++ return 231;
++ case T_AUDIO_INPUT_VOL_LEVEL_8:
++ return 237;
++ case T_AUDIO_INPUT_VOL_LEVEL_9:
++ return 243;
++ case T_AUDIO_INPUT_VOL_LEVEL_10:
++ return 249;
++ case T_AUDIO_INPUT_VOL_LEVEL_11:
++ return 255;
++ default:
++ return 255;
++ }
++}
++
++
++
++#else //default
++
++static struct audio_para_conf init_default_para[] = {
++};
++
++static struct audio_para_conf common_out_para_audio[] = {
++
++};
++
++
++
++static struct audio_para_conf common_in_para_audio[] = {
++};
++
++static struct audio_para_conf hp_outpath_para_audio[] = {
++};
++
++
++static struct audio_para_conf spk_outpath_para_audio[] = {
++};
++
++static struct audio_para_conf main_mic_inpath_para_audio[] = {
++};
++
++static struct audio_para_conf aux_mic_inpath_para_audio[] = {
++};
++
++static struct audio_para_conf handset_inoutpath_para_voice[] = {
++
++};
++
++static struct audio_para_conf headset_inoutpath_para_voice[] = {
++};
++
++static struct audio_para_conf spk_inoutpath_para_voice[] = {
++};
++
++static struct audio_para_conf output_dac_vol = {};
++
++static struct audio_para_conf input_adc_vol = {};
++
++static struct audio_para_conf dac_mute = {};
++static struct audio_para_conf adc_mute = {};
++
++static struct audio_para_conf spk_path_onoff[] = {
++
++};
++static struct audio_para_conf rcv_path_onoff[] = {
++
++};
++static struct audio_para_conf earp_path_onoff[] = {
++
++};
++static int output_vol_conversion(int vol)
++{
++
++ return 24;
++}
++
++static int input_vol_conversion(int vol)
++{
++
++ return 24;
++
++}
++
++
++#endif
++
++static void mix_set_value_wrap(struct mixer *mixer, const char *control, char **values)
++{
++ struct mixer_ctl *ctl;
++ enum mixer_ctl_type type;
++ unsigned int num_ctl_values;
++ unsigned int i;
++
++ if (isdigit(control[0]))
++ ctl = mixer_get_ctl(mixer, atoi(control));
++ else
++ ctl = mixer_get_ctl_by_name(mixer, control);
++
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control(%s)\n",control);
++ return;
++ }
++
++ type = mixer_ctl_get_type(ctl);
++ num_ctl_values = mixer_ctl_get_num_values(ctl);
++
++ if (isdigit(values[0][0])) {
++
++ for (i = 0; i < num_ctl_values; i++) {
++ if (mixer_ctl_set_value(ctl, i, atoi(values[i]))) {
++ fprintf(stderr, "Error: invalid value for index %d\n", i);
++ return;
++ }
++ }
++
++ } else {
++ if (type == MIXER_CTL_TYPE_ENUM) {
++ /*if (num_values != 1) {
++ fprintf(stderr, "Enclose strings in quotes and try again\n");
++ return;
++ }*/
++ if (mixer_ctl_set_enum_by_string(ctl, values[0]))
++ fprintf(stderr, "Error: invalid enum value\n");
++ } else {
++ fprintf(stderr, "Error: only enum types can be set with strings\n");
++ }
++ }
++}
++
++static void mix_get_value_wrap(struct mixer *mixer, const char *control, int *values)
++{
++ struct mixer_ctl *ctl;
++ enum mixer_ctl_type type;
++ unsigned int num_ctl_values;
++ unsigned int i;
++ int val;
++
++ if (isdigit(control[0]))
++ ctl = mixer_get_ctl(mixer, atoi(control));
++ else
++ ctl = mixer_get_ctl_by_name(mixer, control);
++
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control(%s)\n",control);
++ return;
++ }
++
++ type = mixer_ctl_get_type(ctl);
++ num_ctl_values = mixer_ctl_get_num_values(ctl);
++
++
++ for (i = 0; i < num_ctl_values; i++) {
++ val = mixer_ctl_get_value(ctl, i);
++ if (val == -EINVAL) {
++ fprintf(stderr, "Error: invalid value for index %d\n", i);
++ return;
++ }
++ *(values+i) = val;
++ }
++
++}
++
++
++#if (defined _USE_CODEC_TI3100)||(defined _USE_CODEC_AK4940)||(defined _USE_CODEC_NAU8810)||(defined _USE_CODEC_ES8311)||(defined _USE_CODEC_TI3104)
++/*
++int mix_set_input_vol(struct mixer *mixer, int volume)
++{
++ struct mixer_ctl *ctl;
++ char *name = input_adc_vol.control;
++ int num_values, i;
++ int vol = input_vol_conversion(volume);
++
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (i = 0; i < num_values; i++) {
++ mixer_ctl_set_value(ctl, i, vol);
++ }
++
++ return 0;
++}
++
++int mix_set_output_vol(struct mixer *mixer, int volume)
++{
++ struct mixer_ctl *ctl;
++ char *name = output_dac_vol.control;
++ int num_values, i;
++
++ int vol = output_vol_conversion(volume);
++
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (i = 0; i < num_values; i++) {
++ mixer_ctl_set_value(ctl, i, vol);
++ }
++
++ return 0;
++}
++
++int mix_set_output_mute(struct mixer *mixer, bool enable)
++{
++ struct mixer_ctl *ctl;
++ char *name = dac_mute.control;
++ int num_values, i;
++
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (i = 0; i < num_values; i++) {
++ mixer_ctl_set_value(ctl, i, enable);
++ }
++
++ return 0;
++}
++
++int mix_set_input_mute(struct mixer *mixer, bool enable)
++{
++ struct mixer_ctl *ctl;
++ char *name = adc_mute.control;
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ int num_values, i;
++
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (i = 0; i < num_values; i++) {
++ mixer_ctl_set_value(ctl, 0, enable);
++ }
++
++ return 0;
++}
++
++int mix_set_outputpath_onoff(struct mixer *mixer, int path ,bool onoff)
++{
++ struct mixer_ctl *ctl;
++ struct audio_para_conf *path_para;
++ int i, j, num_values, size;
++ switch(path) {
++ case T_OUTPUT_RECEIVER:
++ size = ARRAY_SIZE(rcv_path_onoff);
++ path_para = rcv_path_onoff;
++ break;
++ case T_OUTPUT_SPEAKER:
++ size = ARRAY_SIZE(spk_path_onoff);
++ path_para = spk_path_onoff;
++ break;
++ case T_OUTPUT_HEADSET:
++ size = ARRAY_SIZE(earp_path_onoff);
++ path_para = earp_path_onoff;
++ break;
++ default:
++ return -1;
++ }
++
++ for (i = 0; i < size; i++) {
++ ctl = mixer_get_ctl_by_name(mixer, path_para[i].control);
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (j = 0; j < num_values; j++) {
++ mixer_ctl_set_value(ctl, j, onoff);
++ }
++
++// mix_set_value_wrap(mixer, spk_path_onoff[i].control, spk_path_onoff[i].values);
++ }
++
++ return 0;
++}
++*/
++
++/*
++
++int mix_set_in_call_tone(struct mixer *mixer, int tontype)
++{
++ struct mixer_ctl *ctl;
++ char name[] = "voice tone sel";
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ mixer_ctl_set_value(ctl, 0, tontype);
++
++ return 0;
++}
++
++int mix_set_default_param(struct mixer *mixer)
++{
++ int i;
++ for (i = 0; i < ARRAY_SIZE(init_default_para); i++) {
++ mix_set_value_wrap(mixer, init_default_para[i].control, init_default_para[i].values);
++ }
++
++ return 0;
++}
++
++*/
++
++#define VOCIE_SND_CARD_NUM 0
++
++int mix_set_input_vol(struct mixer *mixer, int volume)
++{
++ struct mixer_ctl *ctl;
++ char *name = input_adc_vol.control;
++ int num_values, i;
++ int vol = input_vol_conversion(volume);
++ if(name == NULL){
++ printf("%s: name is null,return!\n",__func__);
++ return 0;
++
++ }
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (i = 0; i < num_values; i++) {
++ mixer_ctl_set_value(ctl, i, vol);
++ }
++
++ return 0;
++}
++
++int mix_set_output_vol(struct mixer *mixer, int volume)
++{
++ struct mixer_ctl *ctl;
++ char *name = output_dac_vol.control;
++ int num_values, i;
++
++ int vol = output_vol_conversion(volume);
++ if(name == NULL){
++ printf("%s: name is null,return!\n",__func__);
++ return 0;
++
++ }
++
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (i = 0; i < num_values; i++) {
++ mixer_ctl_set_value(ctl, i, vol);
++ }
++
++ return 0;
++}
++
++int mix_set_output_mute(struct mixer *mixer, bool enable)
++{
++ struct mixer_ctl *ctl;
++ char *name = dac_mute.control;
++ int num_values, i;
++ if(name == NULL){
++ printf("%s: name is null,return!\n",__func__);
++ return 0;
++
++ }
++
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (i = 0; i < num_values; i++) {
++ mixer_ctl_set_value(ctl, i, enable);
++ }
++
++ return 0;
++}
++
++int mix_set_input_mute(struct mixer *mixer, bool enable)
++{
++ struct mixer_ctl *ctl;
++ char *name = adc_mute.control;
++ int num_values, i;
++ if(name == NULL){
++ printf("%s: name is null,return!\n",__func__);
++ return 0;
++
++ }
++ ctl = mixer_get_ctl_by_name(mixer, name);
++
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (i = 0; i < num_values; i++) {
++ mixer_ctl_set_value(ctl, 0, enable);
++ }
++
++ return 0;
++}
++
++int mix_set_outputpath_onoff(struct mixer *mixer, int path ,bool onoff)
++{
++ struct mixer_ctl *ctl;
++ struct audio_para_conf *path_para;
++ int i, j, num_values, size;
++ switch(path) {
++ case T_OUTPUT_RECEIVER:
++ size = ARRAY_SIZE(rcv_path_onoff);
++ path_para = rcv_path_onoff;
++ break;
++ case T_OUTPUT_SPEAKER:
++ size = ARRAY_SIZE(spk_path_onoff);
++ path_para = spk_path_onoff;
++ break;
++ case T_OUTPUT_HEADSET:
++ size = ARRAY_SIZE(earp_path_onoff);
++ path_para = earp_path_onoff;
++ break;
++ default:
++ return -1;
++ }
++ if(size == 0){
++ printf("%s: array size is 0,return!\n",__func__);
++ return 0;
++ }
++ for (i = 0; i < size; i++) {
++ ctl = mixer_get_ctl_by_name(mixer, path_para[i].control);
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (j = 0; j < num_values; j++) {
++ mixer_ctl_set_value(ctl, j, onoff);
++ }
++
++// mix_set_value_wrap(mixer, spk_path_onoff[i].control, spk_path_onoff[i].values);
++ }
++
++ return 0;
++}
++
++int mix_set_in_call_tone(struct mixer *mixer, int tontype)
++{
++ struct mixer_ctl *ctl;
++ char name[] = "voice tone sel";
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ mixer_ctl_set_value(ctl, 0, tontype);
++
++ return 0;
++}
++
++int mix_set_default_param(struct mixer *mixer)
++{
++ int i;
++ for (i = 0; i < ARRAY_SIZE(init_default_para); i++) {
++ mix_set_value_wrap(mixer, init_default_para[i].control, init_default_para[i].values);
++ }
++
++ return 0;
++}
++
++int mix_set_voice_vol(struct mixer *mixer, int volume)
++{
++ struct mixer_ctl *ctl;
++ char name[] = "voice processing path Volume";
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ mixer_ctl_set_value(ctl, 0, volume);
++
++ return 0;
++}
++int mix_get_voice_vol(struct mixer *mixer, int *volume)
++{
++
++ mix_get_value_wrap(mixer, "voice processing path Volume", volume);
++
++ return 0;
++
++}
++
++int mix_set_tx_voice_vol(struct mixer *mixer, int volume)
++{
++ struct mixer_ctl *ctl;
++ char name[] = "voice processing tx path Volume";
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ mixer_ctl_set_value(ctl, 0, volume);
++
++ return 0;
++}
++int mix_get_tx_voice_vol(struct mixer *mixer, int *volume)
++{
++
++ mix_get_value_wrap(mixer, "voice processing tx path Volume", volume);
++
++ return 0;
++
++}
++
++
++int mix_set_voice_mute(struct mixer *mixer, bool enable)
++{
++ struct mixer_ctl *ctl;
++ char name[] = "voice uplink mute";
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ mixer_ctl_set_value(ctl, 0, enable);
++
++ return 0;
++}
++int mix_get_voice_mute(struct mixer *mixer, int *enable)
++{
++
++ mix_get_value_wrap(mixer, "voice uplink mute", enable);
++
++ return 0;
++
++}
++
++//voice downlink mute
++
++int mix_set_rx_voice_mute(struct mixer *mixer, bool enable)
++{
++ struct mixer_ctl *ctl;
++ char name[] = "voice downlink mute";
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ mixer_ctl_set_value(ctl, 0, enable);
++
++ return 0;
++}
++int mix_get_rx_voice_mute(struct mixer *mixer, int *enable)
++{
++
++ mix_get_value_wrap(mixer, "voice downlink mute", enable);
++
++ return 0;
++
++}
++
++
++
++
++
++
++int mix_set_output_path(struct mixer *mixer, int path)
++{
++ int i;
++ for (i = 0; i < ARRAY_SIZE(common_out_para_audio); i++) {
++ mix_set_value_wrap(mixer, common_out_para_audio[i].control, common_out_para_audio[i].values);
++ }
++ switch (path) {
++ case T_OUTPUT_RECEIVER:
++ case T_OUTPUT_HEADSET:
++ for (i = 0; i < ARRAY_SIZE(hp_outpath_para_audio); i++) {
++ mix_set_value_wrap(mixer, hp_outpath_para_audio[i].control, hp_outpath_para_audio[i].values);
++ }
++ break;
++ case T_OUTPUT_SPEAKER:
++ for (i = 0; i < ARRAY_SIZE(spk_outpath_para_audio); i++) {
++ mix_set_value_wrap(mixer, spk_outpath_para_audio[i].control, spk_outpath_para_audio[i].values);
++ }
++ break;
++ default:
++ break;
++ }
++
++ return 0;
++}
++
++int mix_set_input_path(struct mixer *mixer, int path)
++{
++ int i;
++ for (i = 0; i < ARRAY_SIZE(common_in_para_audio); i++) {
++ mix_set_value_wrap(mixer, common_in_para_audio[i].control, common_in_para_audio[i].values);
++ }
++
++ #if (defined _USE_CODEC_TI3100)||(defined _USE_CODEC_ES8311)
++ switch (path) {
++ case T_INPUT_MICLP:
++ for (i = 0; i < ARRAY_SIZE(main_mic_inpath_para_audio); i++) {
++ mix_set_value_wrap(mixer, main_mic_inpath_para_audio[i].control, main_mic_inpath_para_audio[i].values);
++ }
++ break;
++ case T_INPUT_MICRP:
++ for (i = 0; i < ARRAY_SIZE(aux_mic_inpath_para_audio); i++) {
++ mix_set_value_wrap(mixer, aux_mic_inpath_para_audio[i].control, aux_mic_inpath_para_audio[i].values);
++ }
++ break;
++ default:
++ break;
++ }
++
++
++ #else
++ switch (path) {
++ case T_INPUT_HANDSET:
++ case T_INPUT_SPEAKER:
++ for (i = 0; i < ARRAY_SIZE(main_mic_inpath_para_audio); i++) {
++ mix_set_value_wrap(mixer, main_mic_inpath_para_audio[i].control, main_mic_inpath_para_audio[i].values);
++ }
++ break;
++ case T_INPUT_HEADSET:
++ for (i = 0; i < ARRAY_SIZE(aux_mic_inpath_para_audio); i++) {
++ mix_set_value_wrap(mixer, aux_mic_inpath_para_audio[i].control, aux_mic_inpath_para_audio[i].values);
++ }
++ break;
++ default:
++ break;
++ }
++ #endif
++
++ return 0;
++}
++/*
++int mix_set_input_vol(struct mixer *mixer, int volume)
++{
++ struct mixer_ctl *ctl;
++ char *name = input_adc_vol.control;
++ int num_values, i;
++ int vol = input_vol_conversion(volume);
++
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (i = 0; i < num_values; i++) {
++ mixer_ctl_set_value(ctl, i, vol);
++ }
++
++ return 0;
++}
++
++int mix_set_output_vol(struct mixer *mixer, int volume)
++{
++ struct mixer_ctl *ctl;
++ char *name = output_dac_vol.control;
++ int num_values, i;
++
++ int vol = output_vol_conversion(volume);
++
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (i = 0; i < num_values; i++) {
++ mixer_ctl_set_value(ctl, i, vol);
++ }
++
++ return 0;
++}
++
++int mix_set_output_mute(struct mixer *mixer, bool enable)
++{
++ struct mixer_ctl *ctl;
++ char *name = dac_mute.control;
++ int num_values, i;
++
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (i = 0; i < num_values; i++) {
++ mixer_ctl_set_value(ctl, i, enable);
++ }
++
++ return 0;
++}
++
++int mix_set_input_mute(struct mixer *mixer, bool enable)
++{
++ struct mixer_ctl *ctl;
++ char *name = adc_mute.control;
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ int num_values, i;
++
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (i = 0; i < num_values; i++) {
++ mixer_ctl_set_value(ctl, 0, enable);
++ }
++
++ return 0;
++}
++
++int mix_set_outputpath_onoff(struct mixer *mixer, int path ,bool onoff)
++{
++ struct mixer_ctl *ctl;
++ struct audio_para_conf *path_para;
++ int i, j, num_values, size;
++ switch(path) {
++ case T_OUTPUT_RECEIVER:
++ size = ARRAY_SIZE(rcv_path_onoff);
++ path_para = rcv_path_onoff;
++ break;
++ case T_OUTPUT_SPEAKER:
++ size = ARRAY_SIZE(spk_path_onoff);
++ path_para = spk_path_onoff;
++ break;
++ case T_OUTPUT_HEADSET:
++ size = ARRAY_SIZE(earp_path_onoff);
++ path_para = earp_path_onoff;
++ break;
++ default:
++ return -1;
++ }
++
++ for (i = 0; i < size; i++) {
++ ctl = mixer_get_ctl_by_name(mixer, path_para[i].control);
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ for (j = 0; j < num_values; j++) {
++ mixer_ctl_set_value(ctl, j, onoff);
++ }
++
++// mix_set_value_wrap(mixer, spk_path_onoff[i].control, spk_path_onoff[i].values);
++ }
++
++ return 0;
++}
++*/
++
++
++
++
++
++
++int mix_set_voice_path(struct mixer *mixer, int path)
++{
++ int i;
++/*
++ for (i = 0; i < ARRAY_SIZE(common_in_para_audio); i++) {
++ tinymix_set_value_test(mixer, common_in_para_audio[i].control, common_in_para_audio[i].values);
++ }
++
++ for(i = 0;i<ARRAY_SIZE(common_out_para_audio);i++)
++ {
++ tinymix_set_value_test(mixer,common_out_para_audio[i].control,common_out_para_audio[i].values);
++ }
++*/
++ switch (path) {
++ case T_OUTPUT_RECEIVER:
++ for (i = 0; i < ARRAY_SIZE(handset_inoutpath_para_voice); i++) {
++ mix_set_value_wrap(mixer, handset_inoutpath_para_voice[i].control, handset_inoutpath_para_voice[i].values);
++ }
++ break;
++ case T_OUTPUT_SPEAKER:
++ for (i = 0; i < ARRAY_SIZE(spk_inoutpath_para_voice); i++) {
++ mix_set_value_wrap(mixer, spk_inoutpath_para_voice[i].control, spk_inoutpath_para_voice[i].values);
++ }
++ break;
++ case T_OUTPUT_HEADSET:
++ for (i = 0; i < ARRAY_SIZE(headset_inoutpath_para_voice); i++) {
++ mix_set_value_wrap(mixer, headset_inoutpath_para_voice[i].control, headset_inoutpath_para_voice[i].values);
++ }
++ default:
++ break;
++ }
++
++ return 0;
++}
++
++
++int mix_get_voice_path(struct mixer *mixer, int *path)
++{
++
++ mix_get_value_wrap(mixer, "audio path select", path);
++
++ return 0;
++
++}
++/*
++
++int mix_set_in_call_tone(struct mixer *mixer, int tontype)
++{
++ struct mixer_ctl *ctl;
++ char name[] = "voice tone sel";
++ ctl = mixer_get_ctl_by_name(mixer, name);
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return -1;
++ }
++
++ mixer_ctl_set_value(ctl, 0, tontype);
++
++ return 0;
++}
++
++int mix_set_default_param(struct mixer *mixer)
++{
++ int i;
++ for (i = 0; i < ARRAY_SIZE(init_default_para); i++) {
++ mix_set_value_wrap(mixer, init_default_para[i].control, init_default_para[i].values);
++ }
++
++ return 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;
++
++
++}
++
++//#ifdef _CPE_AUDIO_PRJ
++#else
++int mix_set_output_path(struct mixer *mixer, int path)
++{
++
++ return 0;
++}
++
++int mix_set_input_path(struct mixer *mixer, int path)
++{
++
++
++ return 0;
++}
++
++int mix_set_input_vol(struct mixer *mixer, int volume)
++{
++
++
++ return 0;
++}
++
++int mix_set_output_vol(struct mixer *mixer, int volume)
++{
++
++
++ return 0;
++}
++
++int mix_set_output_mute(struct mixer *mixer, bool enable)
++{
++
++
++ return 0;
++}
++
++int mix_set_input_mute(struct mixer *mixer, bool enable)
++{
++
++
++ return 0;
++}
++
++int mix_set_outputpath_onoff(struct mixer *mixer, int path ,bool onoff)
++{
++
++ return 0;
++}
++
++
++int mix_set_voice_vol(struct mixer *mixer, int volume)
++{
++
++
++ return 0;
++}
++
++int mix_set_voice_mute(struct mixer *mixer, bool enable)
++{
++
++
++ return 0;
++}
++
++int mix_set_voice_path(struct mixer *mixer, int path)
++{
++ int i;
++
++
++ return 0;
++}
++
++
++int mix_set_in_call_tone(struct mixer *mixer, int tontype)
++{
++
++
++ return 0;
++}
++
++int mix_set_default_param(struct mixer *mixer)
++{
++
++ return 0;
++}
++
++int mix_get_voice_vol(struct mixer *mixer, int *volume)
++{
++
++ return 0;
++}
++
++int mix_set_tx_voice_vol(struct mixer *mixer, int volume)
++{
++ return 0;
++}
++
++int mix_get_tx_voice_vol(struct mixer *mixer, int *volume)
++{
++
++ return 0;
++
++}
++
++int mix_get_voice_mute(struct mixer *mixer, int *enable)
++{
++
++ return 0;
++
++}
++
++//voice downlink mute
++
++int mix_set_rx_voice_mute(struct mixer *mixer, bool enable)
++{
++ return 0;
++}
++int mix_get_rx_voice_mute(struct mixer *mixer, int *enable)
++{
++
++ return 0;
++
++}
++
++int mix_get_voice_path(struct mixer *mixer, int *path)
++{
++
++ return 0;
++
++}
++
++int set_voice_device_mode(int dev_mode)
++{
++ return 0;
++}
++
++#endif
+diff --git a/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/include/tinyalsa/asoundlib.h b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/include/tinyalsa/asoundlib.h
+new file mode 100755
+index 0000000..97ee4f3
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/include/tinyalsa/asoundlib.h
+@@ -0,0 +1,310 @@
++/* asoundlib.h
++**
++** Copyright 2011, The Android Open Source Project
++**
++** Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are met:
++** * Redistributions of source code must retain the above copyright
++** notice, this list of conditions and the following disclaimer.
++** * Redistributions in binary form must reproduce the above copyright
++** notice, this list of conditions and the following disclaimer in the
++** documentation and/or other materials provided with the distribution.
++** * Neither the name of The Android Open Source Project nor the names of
++** its contributors may be used to endorse or promote products derived
++** from this software without specific prior written permission.
++**
++** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
++** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
++** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
++** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++** DAMAGE.
++*/
++
++#ifndef ASOUNDLIB_H
++#define ASOUNDLIB_H
++
++#include <sys/time.h>
++#include <stddef.h>
++
++#if defined(__cplusplus)
++extern "C" {
++#endif
++
++/*
++ * PCM API
++ */
++
++struct pcm;
++
++#define PCM_OUT 0x00000000
++#define PCM_IN 0x10000000
++#define PCM_MMAP 0x00000001
++#define PCM_NOIRQ 0x00000002
++#define PCM_NORESTART 0x00000004 /* PCM_NORESTART - when set, calls to
++ * pcm_write for a playback stream will not
++ * attempt to restart the stream in the case
++ * of an underflow, but will return -EPIPE
++ * instead. After the first -EPIPE error, the
++ * stream is considered to be stopped, and a
++ * second call to pcm_write will attempt to
++ * restart the stream.
++ */
++#define PCM_MONOTONIC 0x00000008 /* see pcm_get_htimestamp */
++
++/* PCM runtime states */
++#define PCM_STATE_OPEN 0
++#define PCM_STATE_SETUP 1
++#define PCM_STATE_PREPARED 2
++#define PCM_STATE_RUNNING 3
++#define PCM_STATE_XRUN 4
++#define PCM_STATE_DRAINING 5
++#define PCM_STATE_PAUSED 6
++#define PCM_STATE_SUSPENDED 7
++#define PCM_STATE_DISCONNECTED 8
++
++/* Bit formats */
++enum pcm_format {
++ PCM_FORMAT_INVALID = -1,
++ PCM_FORMAT_S16_LE = 0, /* 16-bit signed */
++ PCM_FORMAT_S32_LE, /* 32-bit signed */
++ PCM_FORMAT_S8, /* 8-bit signed */
++ PCM_FORMAT_S24_LE, /* 24-bits in 4-bytes */
++ PCM_FORMAT_S24_3LE, /* 24-bits in 3-bytes */
++
++ PCM_FORMAT_MAX,
++};
++
++/* Bitmask has 256 bits (32 bytes) in asound.h */
++struct pcm_mask {
++ unsigned int bits[32 / sizeof(unsigned int)];
++};
++
++/* Configuration for a stream */
++struct pcm_config {
++ unsigned int channels;
++ unsigned int rate;
++ unsigned int period_size;
++ unsigned int period_count;
++ enum pcm_format format;
++
++ /* Values to use for the ALSA start, stop and silence thresholds, and
++ * silence size. Setting any one of these values to 0 will cause the
++ * default tinyalsa values to be used instead.
++ * Tinyalsa defaults are as follows.
++ *
++ * start_threshold : period_count * period_size
++ * stop_threshold : period_count * period_size
++ * silence_threshold : 0
++ * silence_size : 0
++ */
++ unsigned int start_threshold;
++ unsigned int stop_threshold;
++ unsigned int silence_threshold;
++ unsigned int silence_size;
++
++ /* Minimum number of frames available before pcm_mmap_write() will actually
++ * write into the kernel buffer. Only used if the stream is opened in mmap mode
++ * (pcm_open() called with PCM_MMAP flag set). Use 0 for default.
++ */
++ int avail_min;
++};
++
++/* PCM parameters */
++enum pcm_param
++{
++ /* mask parameters */
++ PCM_PARAM_ACCESS,
++ PCM_PARAM_FORMAT,
++ PCM_PARAM_SUBFORMAT,
++ /* interval parameters */
++ PCM_PARAM_SAMPLE_BITS,
++ PCM_PARAM_FRAME_BITS,
++ PCM_PARAM_CHANNELS,
++ PCM_PARAM_RATE,
++ PCM_PARAM_PERIOD_TIME,
++ PCM_PARAM_PERIOD_SIZE,
++ PCM_PARAM_PERIOD_BYTES,
++ PCM_PARAM_PERIODS,
++ PCM_PARAM_BUFFER_TIME,
++ PCM_PARAM_BUFFER_SIZE,
++ PCM_PARAM_BUFFER_BYTES,
++ PCM_PARAM_TICK_TIME,
++};
++
++/* Mixer control types */
++enum mixer_ctl_type {
++ MIXER_CTL_TYPE_BOOL,
++ MIXER_CTL_TYPE_INT,
++ MIXER_CTL_TYPE_ENUM,
++ MIXER_CTL_TYPE_BYTE,
++ MIXER_CTL_TYPE_IEC958,
++ MIXER_CTL_TYPE_INT64,
++ MIXER_CTL_TYPE_UNKNOWN,
++
++ MIXER_CTL_TYPE_MAX,
++};
++
++/* Open and close a stream */
++struct pcm *pcm_open(unsigned int card, unsigned int device,
++ unsigned int flags, struct pcm_config *config);
++int pcm_close(struct pcm *pcm);
++int pcm_is_ready(struct pcm *pcm);
++
++/* Obtain the parameters for a PCM */
++struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
++ unsigned int flags);
++void pcm_params_free(struct pcm_params *pcm_params);
++
++struct pcm_mask *pcm_params_get_mask(struct pcm_params *pcm_params,
++ enum pcm_param param);
++unsigned int pcm_params_get_min(struct pcm_params *pcm_params,
++ enum pcm_param param);
++void pcm_params_set_min(struct pcm_params *pcm_params,
++ enum pcm_param param, unsigned int val);
++unsigned int pcm_params_get_max(struct pcm_params *pcm_params,
++ enum pcm_param param);
++void pcm_params_set_max(struct pcm_params *pcm_params,
++ enum pcm_param param, unsigned int val);
++
++/* Converts the pcm parameters to a human readable string.
++ * The string parameter is a caller allocated buffer of size bytes,
++ * which is then filled up to size - 1 and null terminated,
++ * if size is greater than zero.
++ * The return value is the number of bytes copied to string
++ * (not including null termination) if less than size; otherwise,
++ * the number of bytes required for the buffer.
++ */
++int pcm_params_to_string(struct pcm_params *params, char *string, unsigned int size);
++
++/* Returns 1 if the pcm_format is present (format bit set) in
++ * the pcm_params structure; 0 otherwise, or upon unrecognized format.
++ */
++int pcm_params_format_test(struct pcm_params *params, enum pcm_format format);
++
++/* Set and get config */
++int pcm_get_config(struct pcm *pcm, struct pcm_config *config);
++int pcm_set_config(struct pcm *pcm, struct pcm_config *config);
++
++/* Returns a human readable reason for the last error */
++const char *pcm_get_error(struct pcm *pcm);
++
++/* Returns the sample size in bits for a PCM format.
++ * As with ALSA formats, this is the storage size for the format, whereas the
++ * format represents the number of significant bits. For example,
++ * PCM_FORMAT_S24_LE uses 32 bits of storage.
++ */
++unsigned int pcm_format_to_bits(enum pcm_format format);
++
++/* Returns the buffer size (int frames) that should be used for pcm_write. */
++unsigned int pcm_get_buffer_size(struct pcm *pcm);
++unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames);
++unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes);
++
++/* Returns the pcm latency in ms */
++unsigned int pcm_get_latency(struct pcm *pcm);
++
++/* Returns available frames in pcm buffer and corresponding time stamp.
++ * The clock is CLOCK_MONOTONIC if flag PCM_MONOTONIC was specified in pcm_open,
++ * otherwise the clock is CLOCK_REALTIME.
++ * For an input stream, frames available are frames ready for the
++ * application to read.
++ * For an output stream, frames available are the number of empty frames available
++ * for the application to write.
++ */
++int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail,
++ struct timespec *tstamp);
++
++/* Write data to the fifo.
++ * Will start playback on the first write or on a write that
++ * occurs after a fifo underrun.
++ */
++int pcm_write(struct pcm *pcm, const void *data, unsigned int count);
++int pcm_read(struct pcm *pcm, void *data, unsigned int count);
++
++/*
++ * mmap() support.
++ */
++int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count);
++int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count);
++int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset,
++ unsigned int *frames);
++int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames);
++int pcm_mmap_avail(struct pcm *pcm);
++
++/* Prepare the PCM substream to be triggerable */
++int pcm_prepare(struct pcm *pcm);
++/* Start and stop a PCM channel that doesn't transfer data */
++int pcm_start(struct pcm *pcm);
++int pcm_stop(struct pcm *pcm);
++
++/* ioctl function for PCM driver */
++int pcm_ioctl(struct pcm *pcm, int request, ...);
++
++/* Interrupt driven API */
++int pcm_wait(struct pcm *pcm, int timeout);
++int pcm_get_poll_fd(struct pcm *pcm);
++
++/* Change avail_min after the stream has been opened with no need to stop the stream.
++ * Only accepted if opened with PCM_MMAP and PCM_NOIRQ flags
++ */
++int pcm_set_avail_min(struct pcm *pcm, int avail_min);
++
++/*
++ * MIXER API
++ */
++
++struct mixer;
++struct mixer_ctl;
++
++/* Open and close a mixer */
++struct mixer *mixer_open(unsigned int card);
++void mixer_close(struct mixer *mixer);
++
++/* Get info about a mixer */
++const char *mixer_get_name(struct mixer *mixer);
++
++/* Obtain mixer controls */
++unsigned int mixer_get_num_ctls(struct mixer *mixer);
++struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id);
++struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name);
++
++/* Get info about mixer controls */
++const char *mixer_ctl_get_name(struct mixer_ctl *ctl);
++enum mixer_ctl_type mixer_ctl_get_type(struct mixer_ctl *ctl);
++const char *mixer_ctl_get_type_string(struct mixer_ctl *ctl);
++unsigned int mixer_ctl_get_num_values(struct mixer_ctl *ctl);
++unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl);
++const char *mixer_ctl_get_enum_string(struct mixer_ctl *ctl,
++ unsigned int enum_id);
++
++/* Some sound cards update their controls due to external events,
++ * such as HDMI EDID byte data changing when an HDMI cable is
++ * connected. This API allows the count of elements to be updated.
++ */
++void mixer_ctl_update(struct mixer_ctl *ctl);
++
++/* Set and get mixer controls */
++int mixer_ctl_get_percent(struct mixer_ctl *ctl, unsigned int id);
++int mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent);
++
++int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id);
++int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count);
++int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value);
++int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count);
++int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string);
++
++/* Determe range of integer mixer controls */
++int mixer_ctl_get_range_min(struct mixer_ctl *ctl);
++int mixer_ctl_get_range_max(struct mixer_ctl *ctl);
++
++#if defined(__cplusplus)
++} /* extern "C" */
++#endif
++
++#endif
+diff --git a/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/include/tinyalsa/audio_mixer_ctrl.h b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/include/tinyalsa/audio_mixer_ctrl.h
+new file mode 100755
+index 0000000..da78caa
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/include/tinyalsa/audio_mixer_ctrl.h
+@@ -0,0 +1,96 @@
++#ifndef _AUDIO_MIXER_CTRL_H
++#define _AUDIO_MIXER_CTRL_H
++#include <stdint.h>
++#include <stdbool.h>
++#include <tinyalsa/asoundlib.h>
++#include <sound/asound.h>
++
++enum t_tone_class {
++ T_LOWPOWER_TONE = 0,
++ T_SMS_TONE = 1,
++ T_CALLSTD_TONE = 2,
++ T_ALARM_TONE = 3,
++ T_CALL_TIME_TONE = 4,
++};
++
++enum t_output_path {
++ T_OUTPUT_RECEIVER = 0,
++ T_OUTPUT_HANDSET = T_OUTPUT_RECEIVER,
++ T_OUTPUT_SPEAKER = 1,
++ T_OUTPUT_HEADSET = 2,
++ T_OUTPUT_MAX,
++
++};
++
++
++enum t_input_path {
++ T_INPUT_MICLP = 0,
++ T_INPUT_MICRP = 1,
++ T_INPUT_HANDSET = T_INPUT_MICLP,
++ T_INPUT_SPEAKER = T_INPUT_MICRP,
++ T_INPUT_HEADSET = 2,
++ T_INPUT_MAX,
++};
++
++enum t_audio_out_vol {
++ T_AUDIO_OUTPUT_VOL_LEVEL_0 = 0,
++ T_AUDIO_OUTPUT_VOL_LEVEL_1,
++ T_AUDIO_OUTPUT_VOL_LEVEL_2,
++ T_AUDIO_OUTPUT_VOL_LEVEL_3,
++ T_AUDIO_OUTPUT_VOL_LEVEL_4,
++ T_AUDIO_OUTPUT_VOL_LEVEL_5,
++ T_AUDIO_OUTPUT_VOL_LEVEL_6,
++ T_AUDIO_OUTPUT_VOL_LEVEL_7,
++ T_AUDIO_OUTPUT_VOL_LEVEL_8,
++ T_AUDIO_OUTPUT_VOL_LEVEL_9,
++ T_AUDIO_OUTPUT_VOL_LEVEL_10,
++ T_AUDIO_OUTPUT_VOL_LEVEL_11,
++ T_AUDIO_OUTPUT_VOL_LEVEL_12,
++ T_AUDIO_OUTPUT_VOL_LEVEL_13,
++ T_AUDIO_OUTPUT_VOL_LEVEL_14,
++ T_AUDIO_OUTPUT_VOL_LEVEL_15,
++ T_AUDIO_OUTPUT_VOL_LEVEL_16,
++ T_MAX_AUDIO_OUTPUT_VOL_LEVEL
++};
++
++enum t_audio_in_vol {
++ T_AUDIO_INPUT_VOL_LEVEL_0 = 0,
++ T_AUDIO_INPUT_VOL_LEVEL_1,
++ T_AUDIO_INPUT_VOL_LEVEL_2,
++ T_AUDIO_INPUT_VOL_LEVEL_3,
++ T_AUDIO_INPUT_VOL_LEVEL_4,
++ T_AUDIO_INPUT_VOL_LEVEL_5,
++ T_AUDIO_INPUT_VOL_LEVEL_6,
++ T_AUDIO_INPUT_VOL_LEVEL_7,
++ T_AUDIO_INPUT_VOL_LEVEL_8,
++ T_AUDIO_INPUT_VOL_LEVEL_9,
++ T_AUDIO_INPUT_VOL_LEVEL_10,
++ T_AUDIO_INPUT_VOL_LEVEL_11,
++
++ T_MAX_AUDIO_INPUT_VOL_LEVEL
++} ;
++
++enum t_voice_vol { // volume level for voice
++ T_VOICE_VOL_0_LEVEL = 0,
++ T_VOICE_VOL_1_LEVEL = 1,
++ T_VOICE_VOL_2_LEVEL = 2,
++ T_VOICE_VOL_3_LEVEL = 3,
++ T_VOICE_VOL_4_LEVEL = 4,
++ T_VOICE_VOL_5_LEVEL = 5,
++};
++
++int mix_set_output_path(struct mixer *mixer, int path);
++int mix_set_input_path(struct mixer *mixer, int path);
++int mix_set_input_vol(struct mixer *mixer, int volume);
++int mix_set_output_vol(struct mixer *mixer, int volume);
++int mix_set_output_mute(struct mixer *mixer, bool enable);
++int mix_set_input_mute(struct mixer *mixer, bool enable);
++int mix_set_outputpath_onoff(struct mixer *mixer, int path ,bool onoff);
++int mix_set_voice_vol(struct mixer *mixer, int volume);
++int mix_set_voice_mute(struct mixer *mixer, bool enable);
++int mix_set_voice_path(struct mixer *mixer, int path);
++int mix_set_in_call_tone(struct mixer *mixer, int tontype);
++int mix_set_default_param(struct mixer *mixer);
++int set_voice_device_mode(int dev_mode);
++
++#endif
+diff --git a/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/mixer.c b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/mixer.c
+new file mode 100755
+index 0000000..c4e6765
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/mixer.c
+@@ -0,0 +1,555 @@
++/* mixer.c
++**
++** Copyright 2011, The Android Open Source Project
++**
++** Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are met:
++** * Redistributions of source code must retain the above copyright
++** notice, this list of conditions and the following disclaimer.
++** * Redistributions in binary form must reproduce the above copyright
++** notice, this list of conditions and the following disclaimer in the
++** documentation and/or other materials provided with the distribution.
++** * Neither the name of The Android Open Source Project nor the names of
++** its contributors may be used to endorse or promote products derived
++** from this software without specific prior written permission.
++**
++** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
++** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
++** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
++** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++** DAMAGE.
++*/
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <string.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <ctype.h>
++
++#include <sys/ioctl.h>
++
++#include <linux/ioctl.h>
++#define __force
++#define __bitwise
++#define __user
++#include <sound/asound.h>
++
++#include <tinyalsa/asoundlib.h>
++
++struct mixer_ctl {
++ struct mixer *mixer;
++ struct snd_ctl_elem_info *info;
++ char **ename;
++};
++
++struct mixer {
++ int fd;
++ struct snd_ctl_card_info card_info;
++ struct snd_ctl_elem_info *elem_info;
++ struct mixer_ctl *ctl;
++ unsigned int count;
++};
++
++void mixer_close(struct mixer *mixer)
++{
++ unsigned int n,m;
++
++ if (!mixer)
++ return;
++
++ if (mixer->fd >= 0)
++ close(mixer->fd);
++
++ if (mixer->ctl) {
++ for (n = 0; n < mixer->count; n++) {
++ if (mixer->ctl[n].ename) {
++ unsigned int max = mixer->ctl[n].info->value.enumerated.items;
++ for (m = 0; m < max; m++)
++ free(mixer->ctl[n].ename[m]);
++ free(mixer->ctl[n].ename);
++ }
++ }
++ free(mixer->ctl);
++ }
++
++ if (mixer->elem_info)
++ free(mixer->elem_info);
++
++ free(mixer);
++
++ /* TODO: verify frees */
++}
++
++struct mixer *mixer_open(unsigned int card)
++{
++ struct snd_ctl_elem_list elist;
++ struct snd_ctl_elem_info tmp;
++ struct snd_ctl_elem_id *eid = NULL;
++ struct mixer *mixer = NULL;
++ unsigned int n, m;
++ int fd;
++ char fn[256];
++
++ snprintf(fn, sizeof(fn), "/dev/snd/controlC%u", card);
++ fd = open(fn, O_RDWR);
++ if (fd < 0)
++ return 0;
++
++ memset(&elist, 0, sizeof(elist));
++ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
++ goto fail;
++
++ mixer = calloc(1, sizeof(*mixer));
++ if (!mixer)
++ goto fail;
++
++ mixer->ctl = calloc(elist.count, sizeof(struct mixer_ctl));
++ mixer->elem_info = calloc(elist.count, sizeof(struct snd_ctl_elem_info));
++ if (!mixer->ctl || !mixer->elem_info)
++ goto fail;
++
++ if (ioctl(fd, SNDRV_CTL_IOCTL_CARD_INFO, &mixer->card_info) < 0)
++ goto fail;
++
++ eid = calloc(elist.count, sizeof(struct snd_ctl_elem_id));
++ if (!eid)
++ goto fail;
++
++ mixer->count = elist.count;
++ mixer->fd = fd;
++ elist.space = mixer->count;
++ elist.pids = eid;
++ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
++ goto fail;
++
++ for (n = 0; n < mixer->count; n++) {
++ struct snd_ctl_elem_info *ei = mixer->elem_info + n;
++ ei->id.numid = eid[n].numid;
++ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, ei) < 0)
++ goto fail;
++ mixer->ctl[n].info = ei;
++ mixer->ctl[n].mixer = mixer;
++ if (ei->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
++ char **enames = calloc(ei->value.enumerated.items, sizeof(char*));
++ if (!enames)
++ goto fail;
++ mixer->ctl[n].ename = enames;
++ for (m = 0; m < ei->value.enumerated.items; m++) {
++ memset(&tmp, 0, sizeof(tmp));
++ tmp.id.numid = ei->id.numid;
++ tmp.value.enumerated.item = m;
++ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)
++ goto fail;
++ enames[m] = strdup(tmp.value.enumerated.name);
++ if (!enames[m])
++ goto fail;
++ }
++ }
++ }
++
++ free(eid);
++ return mixer;
++
++fail:
++ /* TODO: verify frees in failure case */
++ if (eid)
++ free(eid);
++ if (mixer)
++ mixer_close(mixer);
++ else if (fd >= 0)
++ close(fd);
++ return 0;
++}
++
++const char *mixer_get_name(struct mixer *mixer)
++{
++ return (const char *)mixer->card_info.name;
++}
++
++unsigned int mixer_get_num_ctls(struct mixer *mixer)
++{
++ if (!mixer)
++ return 0;
++
++ return mixer->count;
++}
++
++struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id)
++{
++ if (mixer && (id < mixer->count))
++ return mixer->ctl + id;
++
++ return NULL;
++}
++
++struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name)
++{
++ unsigned int n;
++
++ if (!mixer)
++ return NULL;
++
++ for (n = 0; n < mixer->count; n++)
++ if (!strcmp(name, (char*) mixer->elem_info[n].id.name))
++ return mixer->ctl + n;
++
++ return NULL;
++}
++
++void mixer_ctl_update(struct mixer_ctl *ctl)
++{
++ ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, ctl->info);
++}
++
++const char *mixer_ctl_get_name(struct mixer_ctl *ctl)
++{
++ if (!ctl)
++ return NULL;
++
++ return (const char *)ctl->info->id.name;
++}
++
++enum mixer_ctl_type mixer_ctl_get_type(struct mixer_ctl *ctl)
++{
++ if (!ctl)
++ return MIXER_CTL_TYPE_UNKNOWN;
++
++ switch (ctl->info->type) {
++ case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return MIXER_CTL_TYPE_BOOL;
++ case SNDRV_CTL_ELEM_TYPE_INTEGER: return MIXER_CTL_TYPE_INT;
++ case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return MIXER_CTL_TYPE_ENUM;
++ case SNDRV_CTL_ELEM_TYPE_BYTES: return MIXER_CTL_TYPE_BYTE;
++ case SNDRV_CTL_ELEM_TYPE_IEC958: return MIXER_CTL_TYPE_IEC958;
++ case SNDRV_CTL_ELEM_TYPE_INTEGER64: return MIXER_CTL_TYPE_INT64;
++ default: return MIXER_CTL_TYPE_UNKNOWN;
++ };
++}
++
++const char *mixer_ctl_get_type_string(struct mixer_ctl *ctl)
++{
++ if (!ctl)
++ return "";
++
++ switch (ctl->info->type) {
++ case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return "BOOL";
++ case SNDRV_CTL_ELEM_TYPE_INTEGER: return "INT";
++ case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return "ENUM";
++ case SNDRV_CTL_ELEM_TYPE_BYTES: return "BYTE";
++ case SNDRV_CTL_ELEM_TYPE_IEC958: return "IEC958";
++ case SNDRV_CTL_ELEM_TYPE_INTEGER64: return "INT64";
++ default: return "Unknown";
++ };
++}
++
++unsigned int mixer_ctl_get_num_values(struct mixer_ctl *ctl)
++{
++ if (!ctl)
++ return 0;
++
++ return ctl->info->count;
++}
++
++static int percent_to_int(struct snd_ctl_elem_info *ei, int percent)
++{
++ int range;
++
++ if (percent > 100)
++ percent = 100;
++ else if (percent < 0)
++ percent = 0;
++
++ range = (ei->value.integer.max - ei->value.integer.min);
++
++ return ei->value.integer.min + (range * percent) / 100;
++}
++
++static int int_to_percent(struct snd_ctl_elem_info *ei, int value)
++{
++ int range = (ei->value.integer.max - ei->value.integer.min);
++
++ if (range == 0)
++ return 0;
++
++ return ((value - ei->value.integer.min) / range) * 100;
++}
++
++int mixer_ctl_get_percent(struct mixer_ctl *ctl, unsigned int id)
++{
++ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
++ return -EINVAL;
++
++ return int_to_percent(ctl->info, mixer_ctl_get_value(ctl, id));
++}
++
++int mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent)
++{
++ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
++ return -EINVAL;
++
++ return mixer_ctl_set_value(ctl, id, percent_to_int(ctl->info, percent));
++}
++
++int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id)
++{
++ struct snd_ctl_elem_value ev;
++ int ret;
++
++ if (!ctl || (id >= ctl->info->count))
++ return -EINVAL;
++
++ memset(&ev, 0, sizeof(ev));
++ ev.id.numid = ctl->info->id.numid;
++ ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
++ if (ret < 0)
++ return ret;
++
++ switch (ctl->info->type) {
++ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
++ return !!ev.value.integer.value[id];
++
++ case SNDRV_CTL_ELEM_TYPE_INTEGER:
++ return ev.value.integer.value[id];
++
++ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
++ return ev.value.enumerated.item[id];
++
++ case SNDRV_CTL_ELEM_TYPE_BYTES:
++ return ev.value.bytes.data[id];
++
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count)
++{
++ struct snd_ctl_elem_value ev;
++ int ret = 0;
++ size_t size;
++ void *source;
++
++ if (!ctl || (count > ctl->info->count) || !count || !array)
++ return -EINVAL;
++
++ memset(&ev, 0, sizeof(ev));
++ ev.id.numid = ctl->info->id.numid;
++
++ switch (ctl->info->type) {
++ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
++ case SNDRV_CTL_ELEM_TYPE_INTEGER:
++ ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
++ if (ret < 0)
++ return ret;
++ size = sizeof(ev.value.integer.value[0]);
++ source = ev.value.integer.value;
++ break;
++
++ case SNDRV_CTL_ELEM_TYPE_BYTES:
++ /* check if this is new bytes TLV */
++ if (ctl->info->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
++ struct snd_ctl_tlv *tlv;
++ int ret;
++
++ if (count > SIZE_MAX - sizeof(*tlv))
++ return -EINVAL;
++ tlv = calloc(1, sizeof(*tlv) + count);
++ if (!tlv)
++ return -ENOMEM;
++ tlv->numid = ctl->info->id.numid;
++ tlv->length = count;
++ ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_TLV_READ, tlv);
++
++ source = tlv->tlv;
++ memcpy(array, source, count);
++
++ free(tlv);
++
++ return ret;
++ } else {
++ ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
++ if (ret < 0)
++ return ret;
++ size = sizeof(ev.value.bytes.data[0]);
++ source = ev.value.bytes.data;
++ break;
++ }
++
++ case SNDRV_CTL_ELEM_TYPE_IEC958:
++ size = sizeof(ev.value.iec958);
++ source = &ev.value.iec958;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ memcpy(array, source, size * count);
++
++ return 0;
++}
++
++int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value)
++{
++ struct snd_ctl_elem_value ev;
++ int ret;
++
++ if (!ctl || (id >= ctl->info->count))
++ return -EINVAL;
++
++ memset(&ev, 0, sizeof(ev));
++ ev.id.numid = ctl->info->id.numid;
++ ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
++ if (ret < 0)
++ return ret;
++
++ switch (ctl->info->type) {
++ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
++ ev.value.integer.value[id] = !!value;
++ break;
++
++ case SNDRV_CTL_ELEM_TYPE_INTEGER:
++ ev.value.integer.value[id] = value;
++ break;
++
++ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
++ ev.value.enumerated.item[id] = value;
++ break;
++
++ case SNDRV_CTL_ELEM_TYPE_BYTES:
++ ev.value.bytes.data[id] = value;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
++}
++
++int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count)
++{
++ struct snd_ctl_elem_value ev;
++ size_t size;
++ void *dest;
++
++ if (!ctl || (count > ctl->info->count) || !count || !array)
++ return -EINVAL;
++
++ memset(&ev, 0, sizeof(ev));
++ ev.id.numid = ctl->info->id.numid;
++
++ switch (ctl->info->type) {
++ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
++ case SNDRV_CTL_ELEM_TYPE_INTEGER:
++ size = sizeof(ev.value.integer.value[0]);
++ dest = ev.value.integer.value;
++ break;
++
++ case SNDRV_CTL_ELEM_TYPE_BYTES:
++ /* check if this is new bytes TLV */
++ if (ctl->info->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
++ struct snd_ctl_tlv *tlv;
++ int ret = 0;
++ if (count > SIZE_MAX - sizeof(*tlv))
++ return -EINVAL;
++ tlv = calloc(1, sizeof(*tlv) + count);
++ if (!tlv)
++ return -ENOMEM;
++ tlv->numid = ctl->info->id.numid;
++ tlv->length = count;
++ memcpy(tlv->tlv, array, count);
++
++ ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_TLV_WRITE, tlv);
++ free(tlv);
++
++ return ret;
++ } else {
++ size = sizeof(ev.value.bytes.data[0]);
++ dest = ev.value.bytes.data;
++ }
++ break;
++
++ case SNDRV_CTL_ELEM_TYPE_IEC958:
++ size = sizeof(ev.value.iec958);
++ dest = &ev.value.iec958;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ memcpy(dest, array, size * count);
++
++ return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
++}
++
++int mixer_ctl_get_range_min(struct mixer_ctl *ctl)
++{
++ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
++ return -EINVAL;
++
++ return ctl->info->value.integer.min;
++}
++
++int mixer_ctl_get_range_max(struct mixer_ctl *ctl)
++{
++ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
++ return -EINVAL;
++
++ return ctl->info->value.integer.max;
++}
++
++unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl)
++{
++ if (!ctl)
++ return 0;
++
++ return ctl->info->value.enumerated.items;
++}
++
++const char *mixer_ctl_get_enum_string(struct mixer_ctl *ctl,
++ unsigned int enum_id)
++{
++ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) ||
++ (enum_id >= ctl->info->value.enumerated.items))
++ return NULL;
++
++ return (const char *)ctl->ename[enum_id];
++}
++
++int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string)
++{
++ unsigned int i, num_enums;
++ struct snd_ctl_elem_value ev;
++ int ret;
++
++ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED))
++ return -EINVAL;
++
++ num_enums = ctl->info->value.enumerated.items;
++ for (i = 0; i < num_enums; i++) {
++ if (!strcmp(string, ctl->ename[i])) {
++ memset(&ev, 0, sizeof(ev));
++ ev.value.enumerated.item[0] = i;
++ ev.id.numid = ctl->info->id.numid;
++ ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
++ if (ret < 0)
++ return ret;
++ return 0;
++ }
++ }
++
++ return -EINVAL;
++}
++
+diff --git a/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/pcm.c b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/pcm.c
+new file mode 100755
+index 0000000..78e1cea
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/pcm.c
+@@ -0,0 +1,1310 @@
++/* pcm.c
++**
++** Copyright 2011, The Android Open Source Project
++**
++** Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are met:
++** * Redistributions of source code must retain the above copyright
++** notice, this list of conditions and the following disclaimer.
++** * Redistributions in binary form must reproduce the above copyright
++** notice, this list of conditions and the following disclaimer in the
++** documentation and/or other materials provided with the distribution.
++** * Neither the name of The Android Open Source Project nor the names of
++** its contributors may be used to endorse or promote products derived
++** from this software without specific prior written permission.
++**
++** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
++** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
++** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
++** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++** DAMAGE.
++*/
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <fcntl.h>
++#include <stdarg.h>
++#include <string.h>
++#include <errno.h>
++#include <unistd.h>
++#include <poll.h>
++
++#include <sys/ioctl.h>
++#include <sys/mman.h>
++#include <sys/time.h>
++#include <limits.h>
++
++#include <linux/ioctl.h>
++#define __force
++#define __bitwise
++#define __user
++#include <sound/asound.h>
++
++#include <tinyalsa/asoundlib.h>
++
++#define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL
++
++/* Logs information into a string; follows snprintf() in that
++ * offset may be greater than size, and though no characters are copied
++ * into string, characters are still counted into offset. */
++#define STRLOG(string, offset, size, ...) \
++ do { int temp, clipoffset = offset > size ? size : offset; \
++ temp = snprintf(string + clipoffset, size - clipoffset, __VA_ARGS__); \
++ if (temp > 0) offset += temp; } while (0)
++
++#ifndef ARRAY_SIZE
++#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
++#endif
++
++/* refer to SNDRV_PCM_ACCESS_##index in sound/asound.h. */
++static const char * const access_lookup[] = {
++ "MMAP_INTERLEAVED",
++ "MMAP_NONINTERLEAVED",
++ "MMAP_COMPLEX",
++ "RW_INTERLEAVED",
++ "RW_NONINTERLEAVED",
++};
++
++/* refer to SNDRV_PCM_FORMAT_##index in sound/asound.h. */
++static const char * const format_lookup[] = {
++ /*[0] =*/ "S8",
++ "U8",
++ "S16_LE",
++ "S16_BE",
++ "U16_LE",
++ "U16_BE",
++ "S24_LE",
++ "S24_BE",
++ "U24_LE",
++ "U24_BE",
++ "S32_LE",
++ "S32_BE",
++ "U32_LE",
++ "U32_BE",
++ "FLOAT_LE",
++ "FLOAT_BE",
++ "FLOAT64_LE",
++ "FLOAT64_BE",
++ "IEC958_SUBFRAME_LE",
++ "IEC958_SUBFRAME_BE",
++ "MU_LAW",
++ "A_LAW",
++ "IMA_ADPCM",
++ "MPEG",
++ /*[24] =*/ "GSM",
++ /* gap */
++ [31] = "SPECIAL",
++ "S24_3LE",
++ "S24_3BE",
++ "U24_3LE",
++ "U24_3BE",
++ "S20_3LE",
++ "S20_3BE",
++ "U20_3LE",
++ "U20_3BE",
++ "S18_3LE",
++ "S18_3BE",
++ "U18_3LE",
++ /*[43] =*/ "U18_3BE",
++#if 0
++ /* recent additions, may not be present on local asound.h */
++ "G723_24",
++ "G723_24_1B",
++ "G723_40",
++ "G723_40_1B",
++ "DSD_U8",
++ "DSD_U16_LE",
++#endif
++};
++
++/* refer to SNDRV_PCM_SUBFORMAT_##index in sound/asound.h. */
++static const char * const subformat_lookup[] = {
++ "STD",
++};
++
++static inline int param_is_mask(int p)
++{
++ return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
++ (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
++}
++
++static inline int param_is_interval(int p)
++{
++ return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) &&
++ (p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL);
++}
++
++static inline struct snd_interval *param_to_interval(struct snd_pcm_hw_params *p, int n)
++{
++ return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]);
++}
++
++static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
++{
++ return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
++}
++
++static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned int bit)
++{
++ if (bit >= SNDRV_MASK_MAX)
++ return;
++ if (param_is_mask(n)) {
++ struct snd_mask *m = param_to_mask(p, n);
++ m->bits[0] = 0;
++ m->bits[1] = 0;
++ m->bits[bit >> 5] |= (1 << (bit & 31));
++ }
++}
++
++static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned int val)
++{
++ if (param_is_interval(n)) {
++ struct snd_interval *i = param_to_interval(p, n);
++ i->min = val;
++ }
++}
++
++static unsigned int param_get_min(struct snd_pcm_hw_params *p, int n)
++{
++ if (param_is_interval(n)) {
++ struct snd_interval *i = param_to_interval(p, n);
++ return i->min;
++ }
++ return 0;
++}
++
++static void param_set_max(struct snd_pcm_hw_params *p, int n, unsigned int val)
++{
++ if (param_is_interval(n)) {
++ struct snd_interval *i = param_to_interval(p, n);
++ i->max = val;
++ }
++}
++
++static unsigned int param_get_max(struct snd_pcm_hw_params *p, int n)
++{
++ if (param_is_interval(n)) {
++ struct snd_interval *i = param_to_interval(p, n);
++ return i->max;
++ }
++ return 0;
++}
++
++static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned int val)
++{
++ if (param_is_interval(n)) {
++ struct snd_interval *i = param_to_interval(p, n);
++ i->min = val;
++ i->max = val;
++ i->integer = 1;
++ }
++}
++
++static unsigned int param_get_int(struct snd_pcm_hw_params *p, int n)
++{
++ if (param_is_interval(n)) {
++ struct snd_interval *i = param_to_interval(p, n);
++ if (i->integer)
++ return i->max;
++ }
++ return 0;
++}
++
++static void param_init(struct snd_pcm_hw_params *p)
++{
++ int n;
++
++ memset(p, 0, sizeof(*p));
++ for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
++ n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
++ struct snd_mask *m = param_to_mask(p, n);
++ m->bits[0] = ~0;
++ m->bits[1] = ~0;
++ }
++ for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
++ n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
++ struct snd_interval *i = param_to_interval(p, n);
++ i->min = 0;
++ i->max = ~0;
++ }
++ p->rmask = ~0U;
++ p->cmask = 0;
++ p->info = ~0U;
++}
++
++#define PCM_ERROR_MAX 128
++
++struct pcm {
++ int fd;
++ unsigned int flags;
++ int running:1;
++ int prepared:1;
++ int underruns;
++ unsigned int buffer_size;
++ unsigned int boundary;
++ char error[PCM_ERROR_MAX];
++ struct pcm_config config;
++ struct snd_pcm_mmap_status *mmap_status;
++ struct snd_pcm_mmap_control *mmap_control;
++ struct snd_pcm_sync_ptr *sync_ptr;
++ void *mmap_buffer;
++ unsigned int noirq_frames_per_msec;
++ int wait_for_avail_min;
++};
++
++unsigned int pcm_get_buffer_size(struct pcm *pcm)
++{
++ return pcm->buffer_size;
++}
++
++const char* pcm_get_error(struct pcm *pcm)
++{
++ return pcm->error;
++}
++
++static int oops(struct pcm *pcm, int e, const char *fmt, ...)
++{
++ va_list ap;
++ int sz;
++
++ va_start(ap, fmt);
++ vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap);
++ va_end(ap);
++ sz = strlen(pcm->error);
++
++ if (errno)
++ snprintf(pcm->error + sz, PCM_ERROR_MAX - sz,
++ ": %s", strerror(e));
++ return -1;
++}
++
++static unsigned int pcm_format_to_alsa(enum pcm_format format)
++{
++ switch (format) {
++ case PCM_FORMAT_S32_LE:
++ return SNDRV_PCM_FORMAT_S32_LE;
++ case PCM_FORMAT_S8:
++ return SNDRV_PCM_FORMAT_S8;
++ case PCM_FORMAT_S24_3LE:
++ return SNDRV_PCM_FORMAT_S24_3LE;
++ case PCM_FORMAT_S24_LE:
++ return SNDRV_PCM_FORMAT_S24_LE;
++ default:
++ case PCM_FORMAT_S16_LE:
++ return SNDRV_PCM_FORMAT_S16_LE;
++ };
++}
++
++unsigned int pcm_format_to_bits(enum pcm_format format)
++{
++ switch (format) {
++ case PCM_FORMAT_S32_LE:
++ case PCM_FORMAT_S24_LE:
++ return 32;
++ case PCM_FORMAT_S24_3LE:
++ return 24;
++ default:
++ case PCM_FORMAT_S16_LE:
++ return 16;
++ };
++}
++
++unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes)
++{
++ return bytes / (pcm->config.channels *
++ (pcm_format_to_bits(pcm->config.format) >> 3));
++}
++
++unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames)
++{
++ return frames * pcm->config.channels *
++ (pcm_format_to_bits(pcm->config.format) >> 3);
++}
++
++static int pcm_sync_ptr(struct pcm *pcm, int flags) {
++ if (pcm->sync_ptr) {
++ pcm->sync_ptr->flags = flags;
++ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SYNC_PTR, pcm->sync_ptr) < 0)
++ return -1;
++ }
++ return 0;
++}
++
++static int pcm_hw_mmap_status(struct pcm *pcm) {
++
++ if (pcm->sync_ptr)
++ return 0;
++
++ int page_size = sysconf(_SC_PAGE_SIZE);
++ pcm->mmap_status = mmap(NULL, page_size, PROT_READ, MAP_FILE | MAP_SHARED,
++ pcm->fd, SNDRV_PCM_MMAP_OFFSET_STATUS);
++ if (pcm->mmap_status == MAP_FAILED)
++ pcm->mmap_status = NULL;
++ if (!pcm->mmap_status)
++ goto mmap_error;
++
++ pcm->mmap_control = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
++ MAP_FILE | MAP_SHARED, pcm->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL);
++ if (pcm->mmap_control == MAP_FAILED)
++ pcm->mmap_control = NULL;
++ if (!pcm->mmap_control) {
++ munmap(pcm->mmap_status, page_size);
++ pcm->mmap_status = NULL;
++ goto mmap_error;
++ }
++ if (pcm->flags & PCM_MMAP)
++ pcm->mmap_control->avail_min = pcm->config.avail_min;
++ else
++ pcm->mmap_control->avail_min = 1;
++
++ return 0;
++
++mmap_error:
++
++ pcm->sync_ptr = calloc(1, sizeof(*pcm->sync_ptr));
++ if (!pcm->sync_ptr)
++ return -ENOMEM;
++ pcm->mmap_status = &pcm->sync_ptr->s.status;
++ pcm->mmap_control = &pcm->sync_ptr->c.control;
++ if (pcm->flags & PCM_MMAP)
++ pcm->mmap_control->avail_min = pcm->config.avail_min;
++ else
++ pcm->mmap_control->avail_min = 1;
++
++ pcm_sync_ptr(pcm, 0);
++
++ return 0;
++}
++
++static void pcm_hw_munmap_status(struct pcm *pcm) {
++ if (pcm->sync_ptr) {
++ free(pcm->sync_ptr);
++ pcm->sync_ptr = NULL;
++ } else {
++ int page_size = sysconf(_SC_PAGE_SIZE);
++ if (pcm->mmap_status)
++ munmap(pcm->mmap_status, page_size);
++ if (pcm->mmap_control)
++ munmap(pcm->mmap_control, page_size);
++ }
++ pcm->mmap_status = NULL;
++ pcm->mmap_control = NULL;
++}
++
++static int pcm_areas_copy(struct pcm *pcm, unsigned int pcm_offset,
++ char *buf, unsigned int src_offset,
++ unsigned int frames)
++{
++ int size_bytes = pcm_frames_to_bytes(pcm, frames);
++ int pcm_offset_bytes = pcm_frames_to_bytes(pcm, pcm_offset);
++ int src_offset_bytes = pcm_frames_to_bytes(pcm, src_offset);
++
++ /* interleaved only atm */
++ if (pcm->flags & PCM_IN)
++ memcpy(buf + src_offset_bytes,
++ (char*)pcm->mmap_buffer + pcm_offset_bytes,
++ size_bytes);
++ else
++ memcpy((char*)pcm->mmap_buffer + pcm_offset_bytes,
++ buf + src_offset_bytes,
++ size_bytes);
++ return 0;
++}
++
++static int pcm_mmap_transfer_areas(struct pcm *pcm, char *buf,
++ unsigned int offset, unsigned int size)
++{
++ void *pcm_areas;
++ int commit;
++ unsigned int pcm_offset, frames, count = 0;
++
++ while (size > 0) {
++ frames = size;
++ pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames);
++ pcm_areas_copy(pcm, pcm_offset, buf, offset, frames);
++ commit = pcm_mmap_commit(pcm, pcm_offset, frames);
++ if (commit < 0) {
++ oops(pcm, commit, "failed to commit %d frames\n", frames);
++ return commit;
++ }
++
++ offset += commit;
++ count += commit;
++ size -= commit;
++ }
++ return count;
++}
++
++int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail,
++ struct timespec *tstamp)
++{
++ int frames;
++ int rc;
++ snd_pcm_uframes_t hw_ptr;
++
++ if (!pcm_is_ready(pcm))
++ return -1;
++
++ rc = pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_APPL|SNDRV_PCM_SYNC_PTR_HWSYNC);
++ if (rc < 0)
++ return -1;
++
++ if ((pcm->mmap_status->state != PCM_STATE_RUNNING) &&
++ (pcm->mmap_status->state != PCM_STATE_DRAINING))
++ return -1;
++
++ *tstamp = pcm->mmap_status->tstamp;
++ if (tstamp->tv_sec == 0 && tstamp->tv_nsec == 0)
++ return -1;
++
++ hw_ptr = pcm->mmap_status->hw_ptr;
++ if (pcm->flags & PCM_IN)
++ frames = hw_ptr - pcm->mmap_control->appl_ptr;
++ else
++ frames = hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr;
++
++ if (frames < 0)
++ frames += pcm->boundary;
++ else if (frames > (int)pcm->boundary)
++ frames -= pcm->boundary;
++
++ *avail = (unsigned int)frames;
++
++ return 0;
++}
++
++int pcm_write(struct pcm *pcm, const void *data, unsigned int count)
++{
++ struct snd_xferi x;
++
++ if (pcm->flags & PCM_IN)
++ return -EINVAL;
++
++ x.buf = (void*)data;
++ x.frames = count / (pcm->config.channels *
++ pcm_format_to_bits(pcm->config.format) / 8);
++
++ for (;;) {
++ if (!pcm->running) {
++ int prepare_error = pcm_prepare(pcm);
++ if (prepare_error)
++ return prepare_error;
++ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))
++ return oops(pcm, errno, "cannot write initial data");
++ pcm->running = 1;
++ return 0;
++ }
++ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) {
++ pcm->prepared = 0;
++ pcm->running = 0;
++ if (errno == EPIPE) {
++ /* we failed to make our window -- try to restart if we are
++ * allowed to do so. Otherwise, simply allow the EPIPE error to
++ * propagate up to the app level */
++ pcm->underruns++;
++ if (pcm->flags & PCM_NORESTART)
++ return -EPIPE;
++ continue;
++ }
++ return oops(pcm, errno, "cannot write stream data");
++ }
++ return 0;
++ }
++}
++
++int pcm_read(struct pcm *pcm, void *data, unsigned int count)
++{
++ struct snd_xferi x;
++
++ if (!(pcm->flags & PCM_IN))
++ return -EINVAL;
++
++ x.buf = data;
++ x.frames = count / (pcm->config.channels *
++ pcm_format_to_bits(pcm->config.format) / 8);
++
++ for (;;) {
++ if (!pcm->running) {
++ if (pcm_start(pcm) < 0) {
++ fprintf(stderr, "start error");
++ return -errno;
++ }
++ }
++ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {
++ pcm->prepared = 0;
++ pcm->running = 0;
++ if (errno == EPIPE) {
++ /* we failed to make our window -- try to restart */
++ pcm->underruns++;
++ continue;
++ }
++ return oops(pcm, errno, "cannot read stream data");
++ }
++ return 0;
++ }
++}
++
++static struct pcm bad_pcm = {
++ .fd = -1,
++};
++
++struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
++ unsigned int flags)
++{
++ struct snd_pcm_hw_params *params;
++ char fn[256];
++ int fd;
++
++ snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
++ flags & PCM_IN ? 'c' : 'p');
++
++ fd = open(fn, O_RDWR);
++ if (fd < 0) {
++ fprintf(stderr, "cannot open device '%s'\n", fn);
++ goto err_open;
++ }
++
++ params = calloc(1, sizeof(struct snd_pcm_hw_params));
++ if (!params)
++ goto err_calloc;
++
++ param_init(params);
++ if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, params)) {
++ fprintf(stderr, "SNDRV_PCM_IOCTL_HW_REFINE error (%d)\n", errno);
++ goto err_hw_refine;
++ }
++
++ close(fd);
++
++ return (struct pcm_params *)params;
++
++err_hw_refine:
++ free(params);
++err_calloc:
++ close(fd);
++err_open:
++ return NULL;
++}
++
++void pcm_params_free(struct pcm_params *pcm_params)
++{
++ struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
++
++ if (params)
++ free(params);
++}
++
++static int pcm_param_to_alsa(enum pcm_param param)
++{
++ switch (param) {
++ case PCM_PARAM_ACCESS:
++ return SNDRV_PCM_HW_PARAM_ACCESS;
++ case PCM_PARAM_FORMAT:
++ return SNDRV_PCM_HW_PARAM_FORMAT;
++ case PCM_PARAM_SUBFORMAT:
++ return SNDRV_PCM_HW_PARAM_SUBFORMAT;
++ case PCM_PARAM_SAMPLE_BITS:
++ return SNDRV_PCM_HW_PARAM_SAMPLE_BITS;
++ break;
++ case PCM_PARAM_FRAME_BITS:
++ return SNDRV_PCM_HW_PARAM_FRAME_BITS;
++ break;
++ case PCM_PARAM_CHANNELS:
++ return SNDRV_PCM_HW_PARAM_CHANNELS;
++ break;
++ case PCM_PARAM_RATE:
++ return SNDRV_PCM_HW_PARAM_RATE;
++ break;
++ case PCM_PARAM_PERIOD_TIME:
++ return SNDRV_PCM_HW_PARAM_PERIOD_TIME;
++ break;
++ case PCM_PARAM_PERIOD_SIZE:
++ return SNDRV_PCM_HW_PARAM_PERIOD_SIZE;
++ break;
++ case PCM_PARAM_PERIOD_BYTES:
++ return SNDRV_PCM_HW_PARAM_PERIOD_BYTES;
++ break;
++ case PCM_PARAM_PERIODS:
++ return SNDRV_PCM_HW_PARAM_PERIODS;
++ break;
++ case PCM_PARAM_BUFFER_TIME:
++ return SNDRV_PCM_HW_PARAM_BUFFER_TIME;
++ break;
++ case PCM_PARAM_BUFFER_SIZE:
++ return SNDRV_PCM_HW_PARAM_BUFFER_SIZE;
++ break;
++ case PCM_PARAM_BUFFER_BYTES:
++ return SNDRV_PCM_HW_PARAM_BUFFER_BYTES;
++ break;
++ case PCM_PARAM_TICK_TIME:
++ return SNDRV_PCM_HW_PARAM_TICK_TIME;
++ break;
++
++ default:
++ return -1;
++ }
++}
++
++struct pcm_mask *pcm_params_get_mask(struct pcm_params *pcm_params,
++ enum pcm_param param)
++{
++ int p;
++ struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
++ if (params == NULL) {
++ return NULL;
++ }
++
++ p = pcm_param_to_alsa(param);
++ if (p < 0 || !param_is_mask(p)) {
++ return NULL;
++ }
++
++ return (struct pcm_mask *)param_to_mask(params, p);
++}
++
++unsigned int pcm_params_get_min(struct pcm_params *pcm_params,
++ enum pcm_param param)
++{
++ struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
++ int p;
++
++ if (!params)
++ return 0;
++
++ p = pcm_param_to_alsa(param);
++ if (p < 0)
++ return 0;
++
++ return param_get_min(params, p);
++}
++
++void pcm_params_set_min(struct pcm_params *pcm_params,
++ enum pcm_param param, unsigned int val)
++{
++ struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
++ int p;
++
++ if (!params)
++ return;
++
++ p = pcm_param_to_alsa(param);
++ if (p < 0)
++ return;
++
++ param_set_min(params, p, val);
++}
++
++unsigned int pcm_params_get_max(struct pcm_params *pcm_params,
++ enum pcm_param param)
++{
++ struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
++ int p;
++
++ if (!params)
++ return 0;
++
++ p = pcm_param_to_alsa(param);
++ if (p < 0)
++ return 0;
++
++ return param_get_max(params, p);
++}
++
++void pcm_params_set_max(struct pcm_params *pcm_params,
++ enum pcm_param param, unsigned int val)
++{
++ struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
++ int p;
++
++ if (!params)
++ return;
++
++ p = pcm_param_to_alsa(param);
++ if (p < 0)
++ return;
++
++ param_set_max(params, p, val);
++}
++
++static int pcm_mask_test(struct pcm_mask *m, unsigned int index)
++{
++ const unsigned int bitshift = 5; /* for 32 bit integer */
++ const unsigned int bitmask = (1 << bitshift) - 1;
++ unsigned int element;
++
++ element = index >> bitshift;
++ if (element >= ARRAY_SIZE(m->bits))
++ return 0; /* for safety, but should never occur */
++ return (m->bits[element] >> (index & bitmask)) & 1;
++}
++
++static int pcm_mask_to_string(struct pcm_mask *m, char *string, unsigned int size,
++ char *mask_name,
++ const char * const *bit_array_name, size_t bit_array_size)
++{
++ unsigned int i;
++ unsigned int offset = 0;
++
++ if (m == NULL)
++ return 0;
++ if (bit_array_size < 32) {
++ STRLOG(string, offset, size, "%12s:\t%#08x\n", mask_name, m->bits[0]);
++ } else { /* spans two or more bitfields, print with an array index */
++ for (i = 0; i < (bit_array_size + 31) >> 5; ++i) {
++ STRLOG(string, offset, size, "%9s[%d]:\t%#08x\n",
++ mask_name, i, m->bits[i]);
++ }
++ }
++ for (i = 0; i < bit_array_size; ++i) {
++ if (pcm_mask_test(m, i)) {
++ STRLOG(string, offset, size, "%12s \t%s\n", "", bit_array_name[i]);
++ }
++ }
++ return offset;
++}
++
++int pcm_params_to_string(struct pcm_params *params, char *string, unsigned int size)
++{
++ struct pcm_mask *m;
++ unsigned int min, max;
++ unsigned int clipoffset, offset;
++
++ m = pcm_params_get_mask(params, PCM_PARAM_ACCESS);
++ offset = pcm_mask_to_string(m, string, size,
++ "Access", access_lookup, ARRAY_SIZE(access_lookup));
++ m = pcm_params_get_mask(params, PCM_PARAM_FORMAT);
++ clipoffset = offset > size ? size : offset;
++ offset += pcm_mask_to_string(m, string + clipoffset, size - clipoffset,
++ "Format", format_lookup, ARRAY_SIZE(format_lookup));
++ m = pcm_params_get_mask(params, PCM_PARAM_SUBFORMAT);
++ clipoffset = offset > size ? size : offset;
++ offset += pcm_mask_to_string(m, string + clipoffset, size - clipoffset,
++ "Subformat", subformat_lookup, ARRAY_SIZE(subformat_lookup));
++ min = pcm_params_get_min(params, PCM_PARAM_RATE);
++ max = pcm_params_get_max(params, PCM_PARAM_RATE);
++ STRLOG(string, offset, size, " Rate:\tmin=%uHz\tmax=%uHz\n", min, max);
++ min = pcm_params_get_min(params, PCM_PARAM_CHANNELS);
++ max = pcm_params_get_max(params, PCM_PARAM_CHANNELS);
++ STRLOG(string, offset, size, " Channels:\tmin=%u\t\tmax=%u\n", min, max);
++ min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS);
++ max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS);
++ STRLOG(string, offset, size, " Sample bits:\tmin=%u\t\tmax=%u\n", min, max);
++ min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE);
++ max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE);
++ STRLOG(string, offset, size, " Period size:\tmin=%u\t\tmax=%u\n", min, max);
++ min = pcm_params_get_min(params, PCM_PARAM_PERIODS);
++ max = pcm_params_get_max(params, PCM_PARAM_PERIODS);
++ STRLOG(string, offset, size, "Period count:\tmin=%u\t\tmax=%u\n", min, max);
++ return offset;
++}
++
++int pcm_params_format_test(struct pcm_params *params, enum pcm_format format)
++{
++ unsigned int alsa_format = pcm_format_to_alsa(format);
++
++ if (alsa_format == SNDRV_PCM_FORMAT_S16_LE && format != PCM_FORMAT_S16_LE)
++ return 0; /* caution: format not recognized is equivalent to S16_LE */
++ return pcm_mask_test(pcm_params_get_mask(params, PCM_PARAM_FORMAT), alsa_format);
++}
++
++int pcm_close(struct pcm *pcm)
++{
++ if (pcm == &bad_pcm)
++ return 0;
++
++ pcm_hw_munmap_status(pcm);
++
++ if (pcm->flags & PCM_MMAP) {
++ pcm_stop(pcm);
++ munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size));
++ }
++
++ if (pcm->fd >= 0)
++ close(pcm->fd);
++ pcm->prepared = 0;
++ pcm->running = 0;
++ pcm->buffer_size = 0;
++ pcm->fd = -1;
++ free(pcm);
++ return 0;
++}
++
++struct pcm *pcm_open(unsigned int card, unsigned int device,
++ unsigned int flags, struct pcm_config *config)
++{
++ struct pcm *pcm;
++ struct snd_pcm_info info;
++ struct snd_pcm_hw_params params;
++ struct snd_pcm_sw_params sparams;
++ char fn[256];
++ int rc;
++
++ pcm = calloc(1, sizeof(struct pcm));
++ if (!pcm || !config)
++ return &bad_pcm; /* TODO: could support default config here */
++
++ pcm->config = *config;
++
++ snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
++ flags & PCM_IN ? 'c' : 'p');
++
++ pcm->flags = flags;
++ pcm->fd = open(fn, O_RDWR|O_NONBLOCK);
++ if (pcm->fd < 0) {
++ oops(pcm, errno, "cannot open device '%s'", fn);
++ return pcm;
++ }
++
++ if (fcntl(pcm->fd, F_SETFL, fcntl(pcm->fd, F_GETFL) &
++ ~O_NONBLOCK) < 0) {
++ oops(pcm, errno, "failed to reset blocking mode '%s'", fn);
++ goto fail_close;
++ }
++
++ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) {
++ oops(pcm, errno, "cannot get info");
++ goto fail_close;
++ }
++
++ param_init(¶ms);
++ param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_FORMAT,
++ pcm_format_to_alsa(config->format));
++ param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_SUBFORMAT,
++ SNDRV_PCM_SUBFORMAT_STD);
++ param_set_min(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, config->period_size);
++ param_set_int(¶ms, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
++ pcm_format_to_bits(config->format));
++ param_set_int(¶ms, SNDRV_PCM_HW_PARAM_FRAME_BITS,
++ pcm_format_to_bits(config->format) * config->channels);
++ param_set_int(¶ms, SNDRV_PCM_HW_PARAM_CHANNELS,
++ config->channels);
++ param_set_int(¶ms, SNDRV_PCM_HW_PARAM_PERIODS, config->period_count);
++ param_set_int(¶ms, SNDRV_PCM_HW_PARAM_RATE, config->rate);
++
++ if (flags & PCM_NOIRQ) {
++ if (!(flags & PCM_MMAP)) {
++ oops(pcm, -EINVAL, "noirq only currently supported with mmap().");
++ goto fail_close;
++ }
++
++ params.flags |= SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP;
++ pcm->noirq_frames_per_msec = config->rate / 1000;
++ }
++
++ if (flags & PCM_MMAP)
++ param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_ACCESS,
++ SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
++ else
++ param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_ACCESS,
++ SNDRV_PCM_ACCESS_RW_INTERLEAVED);
++
++ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms)) {
++ oops(pcm, errno, "cannot set hw params");
++ goto fail_close;
++ }
++
++ /* get our refined hw_params */
++ config->period_size = param_get_int(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
++ config->period_count = param_get_int(¶ms, SNDRV_PCM_HW_PARAM_PERIODS);
++ pcm->buffer_size = config->period_count * config->period_size;
++
++ if (flags & PCM_MMAP) {
++ pcm->mmap_buffer = mmap(NULL, pcm_frames_to_bytes(pcm, pcm->buffer_size),
++ PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, pcm->fd, 0);
++ if (pcm->mmap_buffer == MAP_FAILED) {
++ oops(pcm, -errno, "failed to mmap buffer %d bytes\n",
++ pcm_frames_to_bytes(pcm, pcm->buffer_size));
++ goto fail_close;
++ }
++ }
++
++ memset(&sparams, 0, sizeof(sparams));
++ sparams.tstamp_mode = SNDRV_PCM_TSTAMP_ENABLE;
++ sparams.period_step = 1;
++
++ if (!config->start_threshold) {
++ if (pcm->flags & PCM_IN)
++ pcm->config.start_threshold = sparams.start_threshold = 1;
++ else
++ pcm->config.start_threshold = sparams.start_threshold =
++ config->period_count * config->period_size / 2;
++ } else
++ sparams.start_threshold = config->start_threshold;
++
++ /* pick a high stop threshold - todo: does this need further tuning */
++ if (!config->stop_threshold) {
++ if (pcm->flags & PCM_IN)
++ pcm->config.stop_threshold = sparams.stop_threshold =
++ config->period_count * config->period_size * 10;
++ else
++ pcm->config.stop_threshold = sparams.stop_threshold =
++ config->period_count * config->period_size;
++ }
++ else
++ sparams.stop_threshold = config->stop_threshold;
++
++ if (!pcm->config.avail_min) {
++ if (pcm->flags & PCM_MMAP)
++ pcm->config.avail_min = sparams.avail_min = pcm->config.period_size;
++ else
++ pcm->config.avail_min = sparams.avail_min = 1;
++ } else
++ sparams.avail_min = config->avail_min;
++
++ sparams.xfer_align = config->period_size / 2; /* needed for old kernels */
++ sparams.silence_threshold = config->silence_threshold;
++ sparams.silence_size = config->silence_size;
++ pcm->boundary = sparams.boundary = pcm->buffer_size;
++
++ while (pcm->boundary * 2 <= INT_MAX - pcm->buffer_size)
++ pcm->boundary *= 2;
++
++ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) {
++ oops(pcm, errno, "cannot set sw params");
++ goto fail;
++ }
++
++ rc = pcm_hw_mmap_status(pcm);
++ if (rc < 0) {
++ oops(pcm, rc, "mmap status failed");
++ goto fail;
++ }
++
++#ifdef SNDRV_PCM_IOCTL_TTSTAMP
++ if (pcm->flags & PCM_MONOTONIC) {
++ int arg = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
++ rc = ioctl(pcm->fd, SNDRV_PCM_IOCTL_TTSTAMP, &arg);
++ if (rc < 0) {
++ oops(pcm, rc, "cannot set timestamp type");
++ goto fail;
++ }
++ }
++#endif
++
++ pcm->underruns = 0;
++ return pcm;
++
++fail:
++ if (flags & PCM_MMAP)
++ munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size));
++fail_close:
++ close(pcm->fd);
++ pcm->fd = -1;
++ return pcm;
++}
++
++int pcm_is_ready(struct pcm *pcm)
++{
++ return pcm->fd >= 0;
++}
++
++int pcm_prepare(struct pcm *pcm)
++{
++ if (pcm->prepared)
++ return 0;
++
++ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE) < 0)
++ return oops(pcm, errno, "cannot prepare channel");
++
++ pcm->prepared = 1;
++ return 0;
++}
++
++int pcm_start(struct pcm *pcm)
++{
++ int prepare_error = pcm_prepare(pcm);
++ if (prepare_error)
++ return prepare_error;
++
++ if (pcm->flags & PCM_MMAP)
++ pcm_sync_ptr(pcm, 0);
++
++ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START) < 0)
++ return oops(pcm, errno, "cannot start channel");
++
++ pcm->running = 1;
++ return 0;
++}
++
++int pcm_stop(struct pcm *pcm)
++{
++ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_DROP) < 0)
++ return oops(pcm, errno, "cannot stop channel");
++
++ pcm->prepared = 0;
++ pcm->running = 0;
++ return 0;
++}
++
++static inline int pcm_mmap_playback_avail(struct pcm *pcm)
++{
++ int avail;
++
++ avail = pcm->mmap_status->hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr;
++
++ if (avail < 0)
++ avail += pcm->boundary;
++ else if (avail > (int)pcm->boundary)
++ avail -= pcm->boundary;
++
++ return avail;
++}
++
++static inline int pcm_mmap_capture_avail(struct pcm *pcm)
++{
++ int avail = pcm->mmap_status->hw_ptr - pcm->mmap_control->appl_ptr;
++ if (avail < 0)
++ avail += pcm->boundary;
++ return avail;
++}
++
++int pcm_mmap_avail(struct pcm *pcm)
++{
++ pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_HWSYNC);
++ if (pcm->flags & PCM_IN)
++ return pcm_mmap_capture_avail(pcm);
++ else
++ return pcm_mmap_playback_avail(pcm);
++}
++
++static void pcm_mmap_appl_forward(struct pcm *pcm, int frames)
++{
++ unsigned int appl_ptr = pcm->mmap_control->appl_ptr;
++ appl_ptr += frames;
++
++ /* check for boundary wrap */
++ if (appl_ptr > pcm->boundary)
++ appl_ptr -= pcm->boundary;
++ pcm->mmap_control->appl_ptr = appl_ptr;
++}
++
++int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset,
++ unsigned int *frames)
++{
++ unsigned int continuous, copy_frames, avail;
++
++ /* return the mmap buffer */
++ *areas = pcm->mmap_buffer;
++
++ /* and the application offset in frames */
++ *offset = pcm->mmap_control->appl_ptr % pcm->buffer_size;
++
++ avail = pcm_mmap_avail(pcm);
++ if (avail > pcm->buffer_size)
++ avail = pcm->buffer_size;
++ continuous = pcm->buffer_size - *offset;
++
++ /* we can only copy frames if the are availabale and continuos */
++ copy_frames = *frames;
++ if (copy_frames > avail)
++ copy_frames = avail;
++ if (copy_frames > continuous)
++ copy_frames = continuous;
++ *frames = copy_frames;
++
++ return 0;
++}
++
++int pcm_mmap_commit(struct pcm *pcm, unsigned int offset __attribute__((unused)), unsigned int frames)
++{
++ /* update the application pointer in userspace and kernel */
++ pcm_mmap_appl_forward(pcm, frames);
++ pcm_sync_ptr(pcm, 0);
++
++ return frames;
++}
++
++int pcm_avail_update(struct pcm *pcm)
++{
++ pcm_sync_ptr(pcm, 0);
++ return pcm_mmap_avail(pcm);
++}
++
++int pcm_state(struct pcm *pcm)
++{
++ int err = pcm_sync_ptr(pcm, 0);
++ if (err < 0)
++ return err;
++
++ return pcm->mmap_status->state;
++}
++
++int pcm_set_avail_min(struct pcm *pcm, int avail_min)
++{
++ if ((~pcm->flags) & (PCM_MMAP | PCM_NOIRQ))
++ return -ENOSYS;
++
++ pcm->config.avail_min = avail_min;
++ return 0;
++}
++
++int pcm_wait(struct pcm *pcm, int timeout)
++{
++ struct pollfd pfd;
++ int err;
++
++ pfd.fd = pcm->fd;
++ pfd.events = POLLOUT | POLLERR | POLLNVAL;
++
++ do {
++ /* let's wait for avail or timeout */
++ err = poll(&pfd, 1, timeout);
++ if (err < 0)
++ return -errno;
++
++ /* timeout ? */
++ if (err == 0)
++ return 0;
++
++ /* have we been interrupted ? */
++ if (errno == -EINTR)
++ continue;
++
++ /* check for any errors */
++ if (pfd.revents & (POLLERR | POLLNVAL)) {
++ switch (pcm_state(pcm)) {
++ case PCM_STATE_XRUN:
++ return -EPIPE;
++ case PCM_STATE_SUSPENDED:
++ return -ESTRPIPE;
++ case PCM_STATE_DISCONNECTED:
++ return -ENODEV;
++ default:
++ return -EIO;
++ }
++ }
++ /* poll again if fd not ready for IO */
++ } while (!(pfd.revents & (POLLIN | POLLOUT)));
++
++ return 1;
++}
++
++int pcm_get_poll_fd(struct pcm *pcm)
++{
++ return pcm->fd;
++}
++
++int pcm_mmap_transfer(struct pcm *pcm, const void *buffer, unsigned int bytes)
++{
++ int err = 0, frames, avail;
++ unsigned int offset = 0, count;
++
++ if (bytes == 0)
++ return 0;
++
++ count = pcm_bytes_to_frames(pcm, bytes);
++
++ while (count > 0) {
++
++ /* get the available space for writing new frames */
++ avail = pcm_avail_update(pcm);
++ if (avail < 0) {
++ fprintf(stderr, "cannot determine available mmap frames");
++ return err;
++ }
++
++ /* start the audio if we reach the threshold */
++ if (!pcm->running &&
++ (pcm->buffer_size - avail) >= pcm->config.start_threshold) {
++ if (pcm_start(pcm) < 0) {
++ fprintf(stderr, "start error: hw 0x%x app 0x%x avail 0x%x\n",
++ (unsigned int)pcm->mmap_status->hw_ptr,
++ (unsigned int)pcm->mmap_control->appl_ptr,
++ avail);
++ return -errno;
++ }
++ pcm->wait_for_avail_min = 0;
++ }
++
++ /* sleep until we have space to write new frames */
++ if (pcm->running) {
++ /* enable waiting for avail_min threshold when less frames than we have to write
++ * are available. */
++ if (!pcm->wait_for_avail_min && (count > (unsigned int)avail))
++ pcm->wait_for_avail_min = 1;
++
++ if (pcm->wait_for_avail_min && (avail < pcm->config.avail_min)) {
++ int time = -1;
++
++ /* disable waiting for avail_min threshold to allow small amounts of data to be
++ * written without waiting as long as there is enough room in buffer. */
++ pcm->wait_for_avail_min = 0;
++
++ if (pcm->flags & PCM_NOIRQ)
++ time = (pcm->config.avail_min - avail) / pcm->noirq_frames_per_msec;
++
++ err = pcm_wait(pcm, time);
++ if (err < 0) {
++ pcm->prepared = 0;
++ pcm->running = 0;
++ oops(pcm, err, "wait error: hw 0x%x app 0x%x avail 0x%x\n",
++ (unsigned int)pcm->mmap_status->hw_ptr,
++ (unsigned int)pcm->mmap_control->appl_ptr,
++ avail);
++ pcm->mmap_control->appl_ptr = 0;
++ return err;
++ }
++ continue;
++ }
++ }
++
++ frames = count;
++ if (frames > avail)
++ frames = avail;
++
++ if (!frames)
++ break;
++
++ /* copy frames from buffer */
++ frames = pcm_mmap_transfer_areas(pcm, (void *)buffer, offset, frames);
++ if (frames < 0) {
++ fprintf(stderr, "write error: hw 0x%x app 0x%x avail 0x%x\n",
++ (unsigned int)pcm->mmap_status->hw_ptr,
++ (unsigned int)pcm->mmap_control->appl_ptr,
++ avail);
++ return frames;
++ }
++
++ offset += frames;
++ count -= frames;
++ }
++
++ return 0;
++}
++
++int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count)
++{
++ if ((~pcm->flags) & (PCM_OUT | PCM_MMAP))
++ return -ENOSYS;
++
++ return pcm_mmap_transfer(pcm, (void *)data, count);
++}
++
++int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count)
++{
++ if ((~pcm->flags) & (PCM_IN | PCM_MMAP))
++ return -ENOSYS;
++
++ return pcm_mmap_transfer(pcm, data, count);
++}
++
++int pcm_ioctl(struct pcm *pcm, int request, ...)
++{
++ va_list ap;
++ void * arg;
++
++ if (!pcm_is_ready(pcm))
++ return -1;
++
++ va_start(ap, request);
++ arg = va_arg(ap, void *);
++ va_end(ap);
++
++ return ioctl(pcm->fd, request, arg);
++}
+diff --git a/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinyalsa_voice_ref.c b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinyalsa_voice_ref.c
+new file mode 100755
+index 0000000..9cdc264
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinyalsa_voice_ref.c
+@@ -0,0 +1,122 @@
++/*
++ *
++ * Based on 7510_dev.c
++ *
++ */
++
++#include <tinyalsa/audio_mixer_ctrl.h>
++
++
++struct pcm *voicePcmOut = NULL;
++struct pcm *voicePcmIn = NULL;
++
++typedef struct
++{
++ // uint32_t voice_mode;//0, 2/3g;1, volte nb;2 ,volte wb;
++ uint32_t clock_rate; //8000, 2/3g;8000, volte nb;16000 ,volte wb;
++ uint32_t channel_count;
++ uint32_t samples_per_frame;//160, 2/3g;160, volte nb;320 ,volte wb;
++ uint32_t bits_per_sample;
++} T_voiceCfg;
++
++T_voiceCfg cfgParam = {0,8000,1,160,16};
++
++
++
++
++ int voice_PreOpen(T_voiceCfg *cfgParam)
++{
++ struct mixer *voice_mixer = NULL;
++ struct pcm_config config_voice = {0};
++
++ /* open mixer dev for codec control */
++ voice_mixer = mixer_open(0);
++ if(!voice_mixer)
++ {
++ printf("voice_mixer open failed!");
++ goto err_ret;
++ }
++
++ /* 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
++ voicePcmOut = pcm_open(0, 1, PCM_OUT, &config_voice);
++ if(!voicePcmOut || !pcm_is_ready(voicePcmOut))
++ {
++ printf( "voicePcmOut open failed!");
++ goto err_ret;
++ }
++
++ voicePcmIn = pcm_open(0, 1, PCM_IN, &config_voice);
++ if(!voicePcmIn || !pcm_is_ready(voicePcmIn))
++ {
++ printf( "voicePcmIn open failed!");
++ goto err_ret;
++ }
++
++ if(0 != pcm_prepare(voicePcmOut))
++ {
++ printf("voicePcmOut pcm_prepare failed!");
++ goto err_ret;
++ }
++
++ if(0 != pcm_prepare(voicePcmIn))
++ {
++ printf("voicePcmIn pcm_prepare failed!");
++ goto err_ret;
++ }
++ return 0;
++err_ret:
++ if(voice_mixer)
++ {
++ mixer_close(voice_mixer);
++ voice_mixer = NULL;
++ }
++
++ if(voicePcmOut)
++ {
++ pcm_close(voicePcmOut);
++ voicePcmOut = NULL;
++ }
++ if(voicePcmIn)
++ {
++ pcm_close(voicePcmIn);
++ voicePcmIn = NULL;
++ }
++ return -1;
++
++}
++
++
++ void voice_PreClose(void)
++{
++ if(voicePcmOut)
++ {
++ pcm_close(voicePcmOut);
++ voicePcmOut = NULL;
++ }
++ if(voicePcmIn)
++ {
++ pcm_close(voicePcmIn);
++ voicePcmIn = NULL;
++ }
++}
++
++
+diff --git a/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinycap.c b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinycap.c
+new file mode 100755
+index 0000000..da6f4e9
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinycap.c
+@@ -0,0 +1,237 @@
++/* tinycap.c
++**
++** Copyright 2011, The Android Open Source Project
++**
++** Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are met:
++** * Redistributions of source code must retain the above copyright
++** notice, this list of conditions and the following disclaimer.
++** * Redistributions in binary form must reproduce the above copyright
++** notice, this list of conditions and the following disclaimer in the
++** documentation and/or other materials provided with the distribution.
++** * Neither the name of The Android Open Source Project nor the names of
++** its contributors may be used to endorse or promote products derived
++** from this software without specific prior written permission.
++**
++** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
++** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
++** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
++** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++** DAMAGE.
++*/
++
++#include <tinyalsa/asoundlib.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <signal.h>
++#include <string.h>
++
++#define ID_RIFF 0x46464952
++#define ID_WAVE 0x45564157
++#define ID_FMT 0x20746d66
++#define ID_DATA 0x61746164
++
++#define FORMAT_PCM 1
++
++struct wav_header {
++ uint32_t riff_id;
++ uint32_t riff_sz;
++ uint32_t riff_fmt;
++ uint32_t fmt_id;
++ uint32_t fmt_sz;
++ uint16_t audio_format;
++ uint16_t num_channels;
++ uint32_t sample_rate;
++ uint32_t byte_rate;
++ uint16_t block_align;
++ uint16_t bits_per_sample;
++ uint32_t data_id;
++ uint32_t data_sz;
++};
++
++int capturing = 1;
++
++unsigned int capture_sample(FILE *file, unsigned int card, unsigned int device,
++ unsigned int channels, unsigned int rate,
++ enum pcm_format format, unsigned int period_size,
++ unsigned int period_count);
++
++void sigint_handler(int sig) // __unused)
++{
++ capturing = 0;
++}
++
++int main(int argc, char **argv)
++{
++ FILE *file;
++ struct wav_header header;
++ unsigned int card = 0;
++ unsigned int device = 0;
++ unsigned int channels = 2;
++ unsigned int rate = 44100;
++ unsigned int bits = 16;
++ unsigned int frames;
++ unsigned int period_size = 1024;
++ unsigned int period_count = 4;
++ enum pcm_format format;
++
++ if (argc < 2) {
++ fprintf(stderr, "Usage: %s file.wav [-D card] [-d device] [-c channels] "
++ "[-r rate] [-b bits] [-p period_size] [-n n_periods]\n", argv[0]);
++ return 1;
++ }
++
++ file = fopen(argv[1], "wb");
++ if (!file) {
++ fprintf(stderr, "Unable to create file '%s'\n", argv[1]);
++ return 1;
++ }
++
++ /* parse command line arguments */
++ argv += 2;
++ while (*argv) {
++ if (strcmp(*argv, "-d") == 0) {
++ argv++;
++ if (*argv)
++ device = atoi(*argv);
++ } else if (strcmp(*argv, "-c") == 0) {
++ argv++;
++ if (*argv)
++ channels = atoi(*argv);
++ } else if (strcmp(*argv, "-r") == 0) {
++ argv++;
++ if (*argv)
++ rate = atoi(*argv);
++ } else if (strcmp(*argv, "-b") == 0) {
++ argv++;
++ if (*argv)
++ bits = atoi(*argv);
++ } else if (strcmp(*argv, "-D") == 0) {
++ argv++;
++ if (*argv)
++ card = atoi(*argv);
++ } else if (strcmp(*argv, "-p") == 0) {
++ argv++;
++ if (*argv)
++ period_size = atoi(*argv);
++ } else if (strcmp(*argv, "-n") == 0) {
++ argv++;
++ if (*argv)
++ period_count = atoi(*argv);
++ }
++ if (*argv)
++ argv++;
++ }
++
++ header.riff_id = ID_RIFF;
++ header.riff_sz = 0;
++ header.riff_fmt = ID_WAVE;
++ header.fmt_id = ID_FMT;
++ header.fmt_sz = 16;
++ header.audio_format = FORMAT_PCM;
++ header.num_channels = channels;
++ header.sample_rate = rate;
++
++ switch (bits) {
++ case 32:
++ format = PCM_FORMAT_S32_LE;
++ break;
++ case 24:
++ format = PCM_FORMAT_S24_LE;
++ break;
++ case 16:
++ format = PCM_FORMAT_S16_LE;
++ break;
++ default:
++ fprintf(stderr, "%d bits is not supported.\n", bits);
++ return 1;
++ }
++
++ header.bits_per_sample = pcm_format_to_bits(format);
++ header.byte_rate = (header.bits_per_sample / 8) * channels * rate;
++ header.block_align = channels * (header.bits_per_sample / 8);
++ header.data_id = ID_DATA;
++
++ /* leave enough room for header */
++ fseek(file, sizeof(struct wav_header), SEEK_SET);
++
++ /* install signal handler and begin capturing */
++ signal(SIGINT, sigint_handler);
++ signal(SIGHUP, sigint_handler);
++ signal(SIGTERM, sigint_handler);
++ frames = capture_sample(file, card, device, header.num_channels,
++ header.sample_rate, format,
++ period_size, period_count);
++ printf("Captured %d frames\n", frames);
++
++ /* write header now all information is known */
++ header.data_sz = frames * header.block_align;
++ header.riff_sz = header.data_sz + sizeof(header) - 8;
++ fseek(file, 0, SEEK_SET);
++ fwrite(&header, sizeof(struct wav_header), 1, file);
++
++ fclose(file);
++
++ return 0;
++}
++
++unsigned int capture_sample(FILE *file, unsigned int card, unsigned int device,
++ unsigned int channels, unsigned int rate,
++ enum pcm_format format, unsigned int period_size,
++ unsigned int period_count)
++{
++ struct pcm_config config;
++ struct pcm *pcm;
++ char *buffer;
++ unsigned int size;
++ unsigned int bytes_read = 0;
++
++ memset(&config, 0, sizeof(config));
++ config.channels = channels;
++ config.rate = rate;
++ config.period_size = period_size;
++ config.period_count = period_count;
++ config.format = format;
++ config.start_threshold = 0;
++ config.stop_threshold = 0;
++ config.silence_threshold = 0;
++
++ pcm = pcm_open(card, device, PCM_IN, &config);
++ if (!pcm || !pcm_is_ready(pcm)) {
++ fprintf(stderr, "Unable to open PCM device (%s)\n",
++ pcm_get_error(pcm));
++ return 0;
++ }
++
++ size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
++ buffer = malloc(size);
++ if (!buffer) {
++ fprintf(stderr, "Unable to allocate %d bytes\n", size);
++ free(buffer);
++ pcm_close(pcm);
++ return 0;
++ }
++
++ printf("Capturing sample: %u ch, %u hz, %u bit\n", channels, rate,
++ pcm_format_to_bits(format));
++
++ while (capturing && !pcm_read(pcm, buffer, size)) {
++ if (fwrite(buffer, 1, size, file) != size) {
++ fprintf(stderr,"Error capturing sample\n");
++ break;
++ }
++ bytes_read += size;
++ }
++
++ free(buffer);
++ pcm_close(pcm);
++ return pcm_bytes_to_frames(pcm, bytes_read);
++}
++
+diff --git a/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinymix.c b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinymix.c
+new file mode 100755
+index 0000000..a3c41a2
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinymix.c
+@@ -0,0 +1,316 @@
++/* tinymix.c
++**
++** Copyright 2011, The Android Open Source Project
++**
++** Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are met:
++** * Redistributions of source code must retain the above copyright
++** notice, this list of conditions and the following disclaimer.
++** * Redistributions in binary form must reproduce the above copyright
++** notice, this list of conditions and the following disclaimer in the
++** documentation and/or other materials provided with the distribution.
++** * Neither the name of The Android Open Source Project nor the names of
++** its contributors may be used to endorse or promote products derived
++** from this software without specific prior written permission.
++**
++** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
++** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
++** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
++** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++** DAMAGE.
++*/
++
++#include <tinyalsa/asoundlib.h>
++#include <errno.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <ctype.h>
++#include <string.h>
++
++static void tinymix_list_controls(struct mixer *mixer);
++static void tinymix_detail_control(struct mixer *mixer, const char *control,
++ int print_all);
++static void tinymix_set_value(struct mixer *mixer, const char *control,
++ char **values, unsigned int num_values);
++static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all);
++
++int main(int argc, char **argv)
++{
++ struct mixer *mixer;
++ int card = 0;
++
++ if ((argc > 2) && (strcmp(argv[1], "-D") == 0)) {
++ argv++;
++ if (argv[1]) {
++ card = atoi(argv[1]);
++ argv++;
++ argc -= 2;
++ } else {
++ argc -= 1;
++ }
++ }
++
++ mixer = mixer_open(card);
++ if (!mixer) {
++ fprintf(stderr, "Failed to open mixer\n");
++ return EXIT_FAILURE;
++ }
++
++
++ if (argc == 1) {
++ printf("Mixer name: '%s'\n", mixer_get_name(mixer));
++ tinymix_list_controls(mixer);
++ } else if (argc == 2) {
++ tinymix_detail_control(mixer, argv[1], 1);
++ } else if (argc >= 3) {
++ tinymix_set_value(mixer, argv[1], &argv[2], argc - 2);
++ } else {
++ printf("Usage: tinymix [-D card] [control id] [value to set]\n");
++ }
++
++ mixer_close(mixer);
++
++ return 0;
++}
++
++static void tinymix_list_controls(struct mixer *mixer)
++{
++ struct mixer_ctl *ctl;
++ const char *name, *type;
++ unsigned int num_ctls, num_values;
++ unsigned int i;
++
++ num_ctls = mixer_get_num_ctls(mixer);
++
++ printf("Number of controls: %d\n", num_ctls);
++
++ printf("ctl\ttype\tnum\t%-40s value\n", "name");
++ for (i = 0; i < num_ctls; i++) {
++ ctl = mixer_get_ctl(mixer, i);
++
++ name = mixer_ctl_get_name(ctl);
++ type = mixer_ctl_get_type_string(ctl);
++ num_values = mixer_ctl_get_num_values(ctl);
++ printf("%d\t%s\t%d\t%-40s", i, type, num_values, name);
++ tinymix_detail_control(mixer, name, 0);
++ }
++}
++
++static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all)
++{
++ unsigned int num_enums;
++ unsigned int i;
++ const char *string;
++
++ num_enums = mixer_ctl_get_num_enums(ctl);
++
++ for (i = 0; i < num_enums; i++) {
++ string = mixer_ctl_get_enum_string(ctl, i);
++ if (print_all)
++ printf("\t%s%s", mixer_ctl_get_value(ctl, 0) == (int)i ? ">" : "",
++ string);
++ else if (mixer_ctl_get_value(ctl, 0) == (int)i)
++ printf(" %-s", string);
++ }
++}
++
++static void tinymix_detail_control(struct mixer *mixer, const char *control,
++ int print_all)
++{
++ struct mixer_ctl *ctl;
++ enum mixer_ctl_type type;
++ unsigned int num_values;
++ unsigned int i;
++ int min, max;
++ int ret;
++ char *buf = NULL;
++ size_t len;
++
++ if (isdigit(control[0]))
++ ctl = mixer_get_ctl(mixer, atoi(control));
++ else
++ ctl = mixer_get_ctl_by_name(mixer, control);
++
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return;
++ }
++
++ type = mixer_ctl_get_type(ctl);
++ num_values = mixer_ctl_get_num_values(ctl);
++
++ if (type == MIXER_CTL_TYPE_BYTE) {
++
++ buf = calloc(1, num_values);
++ if (buf == NULL) {
++ fprintf(stderr, "Failed to alloc mem for bytes %d\n", num_values);
++ return;
++ }
++
++ len = num_values;
++ ret = mixer_ctl_get_array(ctl, buf, len);
++ if (ret < 0) {
++ fprintf(stderr, "Failed to mixer_ctl_get_array\n");
++ free(buf);
++ return;
++ }
++ }
++
++ if (print_all)
++ printf("%s:", mixer_ctl_get_name(ctl));
++
++ for (i = 0; i < num_values; i++) {
++ switch (type)
++ {
++ case MIXER_CTL_TYPE_INT:
++ printf(" %d", mixer_ctl_get_value(ctl, i));
++ break;
++ case MIXER_CTL_TYPE_BOOL:
++ printf(" %s", mixer_ctl_get_value(ctl, i) ? "On" : "Off");
++ break;
++ case MIXER_CTL_TYPE_ENUM:
++ tinymix_print_enum(ctl, print_all);
++ break;
++ case MIXER_CTL_TYPE_BYTE:
++ printf("%02x", buf[i]);
++ break;
++ default:
++ printf(" unknown");
++ break;
++ };
++ }
++
++ if (print_all) {
++ if (type == MIXER_CTL_TYPE_INT) {
++ min = mixer_ctl_get_range_min(ctl);
++ max = mixer_ctl_get_range_max(ctl);
++ printf(" (range %d->%d)", min, max);
++ }
++ }
++
++ free(buf);
++
++ printf("\n");
++}
++
++static void tinymix_set_byte_ctl(struct mixer_ctl *ctl,
++ char **values, unsigned int num_values)
++{
++ int ret;
++ char *buf;
++ char *end;
++ unsigned int i;
++ long n;
++
++ buf = calloc(1, num_values);
++ if (buf == NULL) {
++ fprintf(stderr, "set_byte_ctl: Failed to alloc mem for bytes %d\n", num_values);
++ exit(EXIT_FAILURE);
++ }
++
++ for (i = 0; i < num_values; i++) {
++ errno = 0;
++ n = strtol(values[i], &end, 0);
++ if (*end) {
++ fprintf(stderr, "%s not an integer\n", values[i]);
++ goto fail;
++ }
++ if (errno) {
++ fprintf(stderr, "strtol: %s: %s\n", values[i],
++ strerror(errno));
++ goto fail;
++ }
++ if (n < 0 || n > 0xff) {
++ fprintf(stderr, "%s should be between [0, 0xff]\n",
++ values[i]);
++ goto fail;
++ }
++ buf[i] = n;
++ }
++
++ ret = mixer_ctl_set_array(ctl, buf, num_values);
++ if (ret < 0) {
++ fprintf(stderr, "Failed to set binary control\n");
++ goto fail;
++ }
++
++ free(buf);
++ return;
++
++fail:
++ free(buf);
++ exit(EXIT_FAILURE);
++}
++
++static void tinymix_set_value(struct mixer *mixer, const char *control,
++ char **values, unsigned int num_values)
++{
++ struct mixer_ctl *ctl;
++ enum mixer_ctl_type type;
++ unsigned int num_ctl_values;
++ unsigned int i;
++
++ if (isdigit(control[0]))
++ ctl = mixer_get_ctl(mixer, atoi(control));
++ else
++ ctl = mixer_get_ctl_by_name(mixer, control);
++
++ if (!ctl) {
++ fprintf(stderr, "Invalid mixer control\n");
++ return;
++ }
++
++ type = mixer_ctl_get_type(ctl);
++ num_ctl_values = mixer_ctl_get_num_values(ctl);
++
++ if (type == MIXER_CTL_TYPE_BYTE) {
++ tinymix_set_byte_ctl(ctl, values, num_values);
++ return;
++ }
++
++ if (isdigit(values[0][0])) {
++ if (num_values == 1) {
++ /* Set all values the same */
++ int value = atoi(values[0]);
++
++ for (i = 0; i < num_ctl_values; i++) {
++ if (mixer_ctl_set_value(ctl, i, value)) {
++ fprintf(stderr, "Error: invalid value\n");
++ return;
++ }
++ }
++ } else {
++ /* Set multiple values */
++ if (num_values > num_ctl_values) {
++ fprintf(stderr,
++ "Error: %d values given, but control only takes %d\n",
++ num_values, num_ctl_values);
++ return;
++ }
++ for (i = 0; i < num_values; i++) {
++ if (mixer_ctl_set_value(ctl, i, atoi(values[i]))) {
++ fprintf(stderr, "Error: invalid value for index %d\n", i);
++ return;
++ }
++ }
++ }
++ } else {
++ if (type == MIXER_CTL_TYPE_ENUM) {
++ if (num_values != 1) {
++ fprintf(stderr, "Enclose strings in quotes and try again\n");
++ return;
++ }
++ if (mixer_ctl_set_enum_by_string(ctl, values[0]))
++ fprintf(stderr, "Error: invalid enum value\n");
++ } else {
++ fprintf(stderr, "Error: only enum types can be set with strings\n");
++ }
++ }
++}
++
+diff --git a/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinypcminfo.c b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinypcminfo.c
+new file mode 100755
+index 0000000..b2d11bc
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinypcminfo.c
+@@ -0,0 +1,203 @@
++/* tinypcminfo.c
++**
++** Copyright 2012, The Android Open Source Project
++**
++** Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are met:
++** * Redistributions of source code must retain the above copyright
++** notice, this list of conditions and the following disclaimer.
++** * Redistributions in binary form must reproduce the above copyright
++** notice, this list of conditions and the following disclaimer in the
++** documentation and/or other materials provided with the distribution.
++** * Neither the name of The Android Open Source Project nor the names of
++** its contributors may be used to endorse or promote products derived
++** from this software without specific prior written permission.
++**
++** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
++** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
++** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
++** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++** DAMAGE.
++*/
++
++#include <tinyalsa/asoundlib.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#ifndef ARRAY_SIZE
++#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
++#endif
++
++/* The format_lookup is in order of SNDRV_PCM_FORMAT_##index and
++ * matches the grouping in sound/asound.h. Note this is not
++ * continuous and has an empty gap from (25 - 30).
++ */
++static const char *format_lookup[] = {
++ /*[0] =*/ "S8",
++ "U8",
++ "S16_LE",
++ "S16_BE",
++ "U16_LE",
++ "U16_BE",
++ "S24_LE",
++ "S24_BE",
++ "U24_LE",
++ "U24_BE",
++ "S32_LE",
++ "S32_BE",
++ "U32_LE",
++ "U32_BE",
++ "FLOAT_LE",
++ "FLOAT_BE",
++ "FLOAT64_LE",
++ "FLOAT64_BE",
++ "IEC958_SUBFRAME_LE",
++ "IEC958_SUBFRAME_BE",
++ "MU_LAW",
++ "A_LAW",
++ "IMA_ADPCM",
++ "MPEG",
++ /*[24] =*/ "GSM",
++ [31] = "SPECIAL",
++ "S24_3LE",
++ "S24_3BE",
++ "U24_3LE",
++ "U24_3BE",
++ "S20_3LE",
++ "S20_3BE",
++ "U20_3LE",
++ "U20_3BE",
++ "S18_3LE",
++ "S18_3BE",
++ "U18_3LE",
++ /*[43] =*/ "U18_3BE",
++#if 0
++ /* recent additions, may not be present on local asound.h */
++ "G723_24",
++ "G723_24_1B",
++ "G723_40",
++ "G723_40_1B",
++ "DSD_U8",
++ "DSD_U16_LE",
++#endif
++};
++
++/* Returns a human readable name for the format associated with bit_index,
++ * NULL if bit_index is not known.
++ */
++inline const char *pcm_get_format_name(unsigned bit_index)
++{
++ return bit_index < ARRAY_SIZE(format_lookup) ? format_lookup[bit_index] : NULL;
++}
++
++int main(int argc, char **argv)
++{
++ unsigned int device = 0;
++ unsigned int card = 0;
++ int i;
++
++ if (argc < 3) {
++ fprintf(stderr, "Usage: %s -D card -d device\n", argv[0]);
++ return 1;
++ }
++
++ /* parse command line arguments */
++ argv += 1;
++ while (*argv) {
++ if (strcmp(*argv, "-D") == 0) {
++ argv++;
++ if (*argv)
++ card = atoi(*argv);
++ }
++ if (strcmp(*argv, "-d") == 0) {
++ argv++;
++ if (*argv)
++ device = atoi(*argv);
++ }
++ if (*argv)
++ argv++;
++ }
++
++ printf("Info for card %d, device %d:\n", card, device);
++
++ for (i = 0; i < 2; i++) {
++ struct pcm_params *params;
++ struct pcm_mask *m;
++ unsigned int min;
++ unsigned int max;
++
++ printf("\nPCM %s:\n", i == 0 ? "out" : "in");
++
++ params = pcm_params_get(card, device, i == 0 ? PCM_OUT : PCM_IN);
++ if (params == NULL) {
++ printf("Device does not exist.\n");
++ continue;
++ }
++
++ m = pcm_params_get_mask(params, PCM_PARAM_ACCESS);
++ if (m) { /* bitmask, refer to SNDRV_PCM_ACCESS_*, generally interleaved */
++ printf(" Access:\t%#08x\n", m->bits[0]);
++ }
++ m = pcm_params_get_mask(params, PCM_PARAM_FORMAT);
++ if (m) { /* bitmask, refer to: SNDRV_PCM_FORMAT_* */
++ unsigned j, k, count = 0;
++ const unsigned bitcount = sizeof(m->bits[0]) * 8;
++
++ /* we only check first two format masks (out of 8) - others are zero. */
++ printf(" Format[0]:\t%#08x\n", m->bits[0]);
++ printf(" Format[1]:\t%#08x\n", m->bits[1]);
++
++ /* print friendly format names, if they exist */
++ for (k = 0; k < 2; ++k) {
++ for (j = 0; j < bitcount; ++j) {
++ const char *name;
++
++ if (m->bits[k] & (1 << j)) {
++ name = pcm_get_format_name(j + k*bitcount);
++ if (name) {
++ if (count++ == 0) {
++ printf(" Format Name:\t");
++ } else {
++ printf (", ");
++ }
++ printf("%s", name);
++ }
++ }
++ }
++ }
++ if (count) {
++ printf("\n");
++ }
++ }
++ m = pcm_params_get_mask(params, PCM_PARAM_SUBFORMAT);
++ if (m) { /* bitmask, should be 1: SNDRV_PCM_SUBFORMAT_STD */
++ printf(" Subformat:\t%#08x\n", m->bits[0]);
++ }
++ min = pcm_params_get_min(params, PCM_PARAM_RATE);
++ max = pcm_params_get_max(params, PCM_PARAM_RATE);
++ printf(" Rate:\tmin=%uHz\tmax=%uHz\n", min, max);
++ min = pcm_params_get_min(params, PCM_PARAM_CHANNELS);
++ max = pcm_params_get_max(params, PCM_PARAM_CHANNELS);
++ printf(" Channels:\tmin=%u\t\tmax=%u\n", min, max);
++ min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS);
++ max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS);
++ printf(" Sample bits:\tmin=%u\t\tmax=%u\n", min, max);
++ min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE);
++ max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE);
++ printf(" Period size:\tmin=%u\t\tmax=%u\n", min, max);
++ min = pcm_params_get_min(params, PCM_PARAM_PERIODS);
++ max = pcm_params_get_max(params, PCM_PARAM_PERIODS);
++ printf("Period count:\tmin=%u\t\tmax=%u\n", min, max);
++
++ pcm_params_free(params);
++ }
++
++ return 0;
++}
+diff --git a/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinyplay.c b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinyplay.c
+new file mode 100755
+index 0000000..88c54ae
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/libtinyalsa/files/libtinyalsa/tinyplay.c
+@@ -0,0 +1,272 @@
++/* tinyplay.c
++**
++** Copyright 2011, The Android Open Source Project
++**
++** Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are met:
++** * Redistributions of source code must retain the above copyright
++** notice, this list of conditions and the following disclaimer.
++** * Redistributions in binary form must reproduce the above copyright
++** notice, this list of conditions and the following disclaimer in the
++** documentation and/or other materials provided with the distribution.
++** * Neither the name of The Android Open Source Project nor the names of
++** its contributors may be used to endorse or promote products derived
++** from this software without specific prior written permission.
++**
++** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
++** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
++** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
++** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
++** DAMAGE.
++*/
++
++#include <tinyalsa/asoundlib.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <string.h>
++#include <signal.h>
++
++#define ID_RIFF 0x46464952
++#define ID_WAVE 0x45564157
++#define ID_FMT 0x20746d66
++#define ID_DATA 0x61746164
++
++struct riff_wave_header {
++ uint32_t riff_id;
++ uint32_t riff_sz;
++ uint32_t wave_id;
++};
++
++struct chunk_header {
++ uint32_t id;
++ uint32_t sz;
++};
++
++struct chunk_fmt {
++ uint16_t audio_format;
++ uint16_t num_channels;
++ uint32_t sample_rate;
++ uint32_t byte_rate;
++ uint16_t block_align;
++ uint16_t bits_per_sample;
++};
++
++static int close = 0;
++
++void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,
++ unsigned int rate, unsigned int bits, unsigned int period_size,
++ unsigned int period_count);
++
++void stream_close(int sig)
++{
++ /* allow the stream to be closed gracefully */
++ signal(sig, SIG_IGN);
++ close = 1;
++}
++
++int main(int argc, char **argv)
++{
++ FILE *file;
++ struct riff_wave_header riff_wave_header;
++ struct chunk_header chunk_header;
++ struct chunk_fmt chunk_fmt;
++ unsigned int device = 0;
++ unsigned int card = 0;
++ unsigned int period_size = 1024;
++ unsigned int period_count = 4;
++ char *filename;
++ int more_chunks = 1;
++
++ if (argc < 2) {
++ fprintf(stderr, "Usage: %s file.wav [-D card] [-d device] [-p period_size]"
++ " [-n n_periods] \n", argv[0]);
++ return 1;
++ }
++
++ filename = argv[1];
++ file = fopen(filename, "rb");
++ if (!file) {
++ fprintf(stderr, "Unable to open file '%s'\n", filename);
++ return 1;
++ }
++
++ fread(&riff_wave_header, sizeof(riff_wave_header), 1, file);
++ if ((riff_wave_header.riff_id != ID_RIFF) ||
++ (riff_wave_header.wave_id != ID_WAVE)) {
++ fprintf(stderr, "Error: '%s' is not a riff/wave file\n", filename);
++ fclose(file);
++ return 1;
++ }
++
++ do {
++ fread(&chunk_header, sizeof(chunk_header), 1, file);
++
++ switch (chunk_header.id) {
++ case ID_FMT:
++ fread(&chunk_fmt, sizeof(chunk_fmt), 1, file);
++ /* If the format header is larger, skip the rest */
++ if (chunk_header.sz > sizeof(chunk_fmt))
++ fseek(file, chunk_header.sz - sizeof(chunk_fmt), SEEK_CUR);
++ break;
++ case ID_DATA:
++ /* Stop looking for chunks */
++ more_chunks = 0;
++ break;
++ default:
++ /* Unknown chunk, skip bytes */
++ fseek(file, chunk_header.sz, SEEK_CUR);
++ }
++ } while (more_chunks);
++
++ /* parse command line arguments */
++ argv += 2;
++ while (*argv) {
++ if (strcmp(*argv, "-d") == 0) {
++ argv++;
++ if (*argv)
++ device = atoi(*argv);
++ }
++ if (strcmp(*argv, "-p") == 0) {
++ argv++;
++ if (*argv)
++ period_size = atoi(*argv);
++ }
++ if (strcmp(*argv, "-n") == 0) {
++ argv++;
++ if (*argv)
++ period_count = atoi(*argv);
++ }
++ if (strcmp(*argv, "-D") == 0) {
++ argv++;
++ if (*argv)
++ card = atoi(*argv);
++ }
++ if (*argv)
++ argv++;
++ }
++
++ play_sample(file, card, device, chunk_fmt.num_channels, chunk_fmt.sample_rate,
++ chunk_fmt.bits_per_sample, period_size, period_count);
++
++ fclose(file);
++
++ return 0;
++}
++
++int check_param(struct pcm_params *params, unsigned int param, unsigned int value,
++ char *param_name, char *param_unit)
++{
++ unsigned int min;
++ unsigned int max;
++ int is_within_bounds = 1;
++
++ min = pcm_params_get_min(params, param);
++ if (value < min) {
++ fprintf(stderr, "%s is %u%s, device only supports >= %u%s\n", param_name, value,
++ param_unit, min, param_unit);
++ is_within_bounds = 0;
++ }
++
++ max = pcm_params_get_max(params, param);
++ if (value > max) {
++ fprintf(stderr, "%s is %u%s, device only supports <= %u%s\n", param_name, value,
++ param_unit, max, param_unit);
++ is_within_bounds = 0;
++ }
++
++ return is_within_bounds;
++}
++
++int sample_is_playable(unsigned int card, unsigned int device, unsigned int channels,
++ unsigned int rate, unsigned int bits, unsigned int period_size,
++ unsigned int period_count)
++{
++ struct pcm_params *params;
++ int can_play;
++
++ params = pcm_params_get(card, device, PCM_OUT);
++ if (params == NULL) {
++ fprintf(stderr, "Unable to open PCM device %u.\n", device);
++ return 0;
++ }
++
++ can_play = check_param(params, PCM_PARAM_RATE, rate, "Sample rate", "Hz");
++ can_play &= check_param(params, PCM_PARAM_CHANNELS, channels, "Sample", " channels");
++ can_play &= check_param(params, PCM_PARAM_SAMPLE_BITS, bits, "Bitrate", " bits");
++ can_play &= check_param(params, PCM_PARAM_PERIOD_SIZE, period_size, "Period size", "Hz");
++ can_play &= check_param(params, PCM_PARAM_PERIODS, period_count, "Period count", "Hz");
++
++ pcm_params_free(params);
++
++ return can_play;
++}
++
++void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,
++ unsigned int rate, unsigned int bits, unsigned int period_size,
++ unsigned int period_count)
++{
++ struct pcm_config config;
++ struct pcm *pcm;
++ char *buffer;
++ int size;
++ int num_read;
++
++ memset(&config, 0, sizeof(config));
++ config.channels = channels;
++ config.rate = rate;
++ config.period_size = period_size;
++ config.period_count = period_count;
++ if (bits == 32)
++ config.format = PCM_FORMAT_S32_LE;
++ else if (bits == 16)
++ config.format = PCM_FORMAT_S16_LE;
++ config.start_threshold = 0;
++ config.stop_threshold = 0;
++ config.silence_threshold = 0;
++
++ if (!sample_is_playable(card, device, channels, rate, bits, period_size, period_count)) {
++ return;
++ }
++
++ pcm = pcm_open(card, device, PCM_OUT, &config);
++ if (!pcm || !pcm_is_ready(pcm)) {
++ fprintf(stderr, "Unable to open PCM device %u (%s)\n",
++ device, pcm_get_error(pcm));
++ return;
++ }
++
++ size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
++ buffer = malloc(size);
++ if (!buffer) {
++ fprintf(stderr, "Unable to allocate %d bytes\n", size);
++ free(buffer);
++ pcm_close(pcm);
++ return;
++ }
++
++ printf("Playing sample: %u ch, %u hz, %u bit\n", channels, rate, bits);
++
++ /* catch ctrl-c to shutdown cleanly */
++ signal(SIGINT, stream_close);
++
++ do {
++ num_read = fread(buffer, 1, size, file);
++ if (num_read > 0) {
++ if (pcm_write(pcm, buffer, num_read)) {
++ fprintf(stderr, "Error playing sample\n");
++ break;
++ }
++ }
++ } while (!close && num_read > 0);
++
++ free(buffer);
++ pcm_close(pcm);
++}
++
+diff --git a/esdk/layers/meta-zxic/recipes-app/libvoice/libvoice.bb b/esdk/layers/meta-zxic/recipes-app/libvoice/libvoice.bb
+index 02b81b9..b413ee2 100755
+--- a/esdk/layers/meta-zxic/recipes-app/libvoice/libvoice.bb
++++ b/esdk/layers/meta-zxic/recipes-app/libvoice/libvoice.bb
+@@ -16,6 +16,8 @@
+ #引用公用头文件和编译选项。
+ include ${BSPDIR}/sources/meta-zxic/conf/app_com.inc
+ CFLAGS_append = "-I ${BSPDIR}/zxic_code/zxic_source/zxic_app_open/platform/libtinyalsa/include"
++CFLAGS_append = "-I ${BSPDIR}/zxic_code/zxic_source/linux-5.10/include/linux"
++
+
+ CFLAGS_append += "${@bb.utils.contains("CONFIG_VB_TRANSMIT_INTF", "RTP", "-I ${BSPDIR}/zxic_code/zxic_source/zxic_app/librtp/include", "", d)}"
+ DEPENDS += "${@bb.utils.contains('CONFIG_VB_TRANSMIT_INTF', 'RTP', 'librtp', '', d)}"
+diff --git a/esdk/layers/meta-zxic/recipes-app/sntp/sntp.bb b/esdk/layers/meta-zxic/recipes-app/sntp/sntp.bb
+index 21f207e..dd579d3 100755
+--- a/esdk/layers/meta-zxic/recipes-app/sntp/sntp.bb
++++ b/esdk/layers/meta-zxic/recipes-app/sntp/sntp.bb
+@@ -1,6 +1,6 @@
+ DESCRIPTION = "sntp"
+ #sntp依赖libnvram库
+-DEPENDS = "libnvram libsoftap libsofttimer"
++DEPENDS = "libdebug-info libnvram libsoftap libsofttimer"
+ SECTION = "app"
+ LICENSE = "zte"
+ PV = "1.0.0"
+@@ -26,7 +26,8 @@
+
+ #引用公用头文件和编译选项。
+ include ${BSPDIR}/sources/meta-zxic/conf/app_com.inc
+-
++include ${BSPDIR}/sources/meta-zxic/conf/pub.inc
++CFLAGS_append += "${ZXIC_EXTRA_CFLAGS}"
+ #编译
+ do_compile() {
+ make -C sntp
+@@ -49,7 +50,7 @@
+ if ${@bb.utils.contains('DISTRO_FEATURES','sysvinit','true','false',d)}; then
+ install -Dm 0755 ${WORKDIR}/sntp.sysvinit ${D}${sysconfdir}/init.d/sntp
+ install -d ${D}${sysconfdir}/rcS.d
+- #ln -s ../init.d/sntp ${D}${sysconfdir}/rcS.d/S22sntp
++ ln -s ../init.d/sntp ${D}${sysconfdir}/rcS.d/S22sntp
+ fi
+
+ #install elfs
+@@ -72,4 +73,4 @@
+ SYSTEMD_SERVICE_${PN} = "sntp.service"
+ SYSTEMD_AUTO_ENABLE_${PN} = "enable"
+
+-RDEPENDS_${PN} = " libnvram libsoftap libsofttimer"
++RDEPENDS_${PN} = " libdebug-info libnvram libsoftap libsofttimer"
+\ No newline at end of file
+diff --git a/esdk/layers/meta-zxic/recipes-app/softap-demo/softap-demo.bb b/esdk/layers/meta-zxic/recipes-app/softap-demo/softap-demo.bb
+index b519bca..67b62d6 100755
+--- a/esdk/layers/meta-zxic/recipes-app/softap-demo/softap-demo.bb
++++ b/esdk/layers/meta-zxic/recipes-app/softap-demo/softap-demo.bb
+@@ -1,5 +1,5 @@
+ DESCRIPTION = "softap_demo"
+-DEPENDS = "libsoftap libatutils libsofttimer libnvram"
++DEPENDS = "libsoftap libatutils libsofttimer libnvram libatreg"
+ SECTION = "app"
+ LICENSE = "zte"
+ PV = "1.0.0"
+@@ -61,4 +61,4 @@
+ SYSTEMD_SERVICE_${PN} = "softap_demo.service"
+ SYSTEMD_AUTO_ENABLE_${PN} = "disable"
+
+-RDEPENDS_${PN} = " libsoftap libatutils libsofttimer libnvram"
++RDEPENDS_${PN} = " libsoftap libatutils libsofttimer libnvram libatreg"
+diff --git a/esdk/layers/meta-zxic/recipes-app/vb-demo/vb-demo.bb b/esdk/layers/meta-zxic/recipes-app/vb-demo/vb-demo.bb
+new file mode 100755
+index 0000000..68f2fd2
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/vb-demo/vb-demo.bb
+@@ -0,0 +1,64 @@
++DESCRIPTION = "vb_demo"
++DEPENDS = "libvoice"
++SECTION = "app"
++LICENSE = "zte"
++PV = "1.0.0"
++PR = "r0"
++
++CLASS_COM = " \
++ ${@bb.utils.contains('DISTRO_FEATURES', 'procd', 'openwrt openwrt-services', '', d)} \
++ ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)} \
++"
++inherit ${CLASS_COM}
++
++#配置code路径信息。
++FILESEXTRAPATHS_prepend :="${APP-OPEN-PATH}:"
++SRC_URI = " \
++ file://test/vb_demo \
++ ${@bb.utils.contains("DISTRO_FEATURES", "procd", "file://vb_demo.init","", d)} \
++ ${@bb.utils.contains("DISTRO_FEATURES", "systemd", "file://vb_demo.service","", d)} \
++ "
++LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/zte;md5=c075689d1d1e06d4ab5bbe53623a6808"
++S = "${WORKDIR}"
++S_SRC_PATH = "${S}/test/vb_demo"
++#引用公用头文件和编译选项。
++include ${BSPDIR}/sources/meta-zxic/conf/app_com.inc
++
++#inherit autotools pkgconfig systemd
++
++do_compile() {
++ make -C ${S_SRC_PATH}
++}
++
++do_install () {
++ install -d ${D}${bindir}/
++ install -m 0755 ${S_SRC_PATH}/vb_demo ${D}${bindir}/
++
++ if ${@bb.utils.contains('DISTRO_FEATURES','procd','true','false',d)}; then
++ install -Dm 0755 ${WORKDIR}/vb_demo.init ${D}${sysconfdir}/init.d/vb_demo
++ fi
++
++ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
++ install -d ${D}${systemd_unitdir}/system
++ install -m 0644 ${WORKDIR}/vb_demo.service ${D}${systemd_unitdir}/system
++ fi
++
++ #install elfs
++ install -d ${ELFS-PATH}/
++ install -m 0755 ${S_SRC_PATH}/vb_demo ${ELFS-PATH}/
++}
++
++do_cleanlibs () {
++ rm -fr ${ELFS-PATH}/vb_demo
++}
++
++addtask cleanlibs after do_clean before do_cleansstate
++
++FILES_${PN} = "\
++ ${bindir}/ \
++ ${@bb.utils.contains("DISTRO_FEATURES", "procd", "${sysconfdir}/init.d/vb_demo","", d)} \
++ "
++SYSTEMD_SERVICE_${PN} = "vb_demo.service"
++SYSTEMD_AUTO_ENABLE_${PN} = "disable"
++
++RDEPENDS_${PN} = " libvoice"
+diff --git a/esdk/layers/meta-zxic/recipes-app/vb-demo/vb-demo/vb_demo.init b/esdk/layers/meta-zxic/recipes-app/vb-demo/vb-demo/vb_demo.init
+new file mode 100755
+index 0000000..e05899f
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/vb-demo/vb-demo/vb_demo.init
+@@ -0,0 +1,21 @@
++#!/bin/sh /etc/rc.common
++
++START=18
++STOP=85
++USE_PROCD=1
++
++logger -t vb_demo
++
++start_service() {
++ procd_open_instance
++ procd_set_param command /usr/bin/vb_demo
++ procd_set_param stdout 1 # forward stdout of the command to logd
++ procd_set_param stderr 1 # same for stderr
++ procd_set_param respawn
++ procd_close_instance
++}
++
++stop_service()
++{
++ echo "add clean code"
++}
+diff --git a/esdk/layers/meta-zxic/recipes-app/vb-demo/vb-demo/vb_demo.service b/esdk/layers/meta-zxic/recipes-app/vb-demo/vb-demo/vb_demo.service
+new file mode 100755
+index 0000000..d519809
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/vb-demo/vb-demo/vb_demo.service
+@@ -0,0 +1,11 @@
++[Unit]
++Description=The vb_demo service
++
++[Service]
++Type=simple
++ExecStart=/usr/bin/vb_demo
++Restart=always
++
++[Install]
++WantedBy=basic.target
++
+diff --git a/esdk/layers/meta-zxic/recipes-app/wifi-demo/wifi-demo.bb b/esdk/layers/meta-zxic/recipes-app/wifi-demo/wifi-demo.bb
+index 5565218..574baff 100755
+--- a/esdk/layers/meta-zxic/recipes-app/wifi-demo/wifi-demo.bb
++++ b/esdk/layers/meta-zxic/recipes-app/wifi-demo/wifi-demo.bb
+@@ -32,16 +32,19 @@
+ install -d ${D}${bindir}/
+ install -m 0755 ${S}/wifi_demo/wifi_demo ${D}${bindir}/
+ install -m 0755 ${S}/wifi_demo/apsta_demo ${D}${bindir}/
++ install -m 0755 ${S}/wifi_demo/wifi_testmode_demo ${D}${bindir}/
+
+ #install elfs
+ install -d ${ELFS-PATH}/
+ install -m 0755 ${S}/wifi_demo/wifi_demo ${ELFS-PATH}/
+ install -m 0755 ${S}/wifi_demo/apsta_demo ${ELFS-PATH}/
++ install -m 0755 ${S}/wifi_demo/wifi_testmode_demo ${ELFS-PATH}/
+ }
+
+ do_cleanlibs () {
+ rm -fr ${ELFS-PATH}/wifi_demo
+ rm -fr ${ELFS-PATH}/apsta_demo
++ rm -fr ${ELFS-PATH}/wifi_testmode_demo
+ }
+
+ addtask cleanlibs after do_clean before do_cleansstate
+diff --git a/esdk/layers/meta-zxic/recipes-app/zxic-debug/zxic-debug.bb b/esdk/layers/meta-zxic/recipes-app/zxic-debug/zxic-debug.bb
+index c7f87d1..61650fa 100755
+--- a/esdk/layers/meta-zxic/recipes-app/zxic-debug/zxic-debug.bb
++++ b/esdk/layers/meta-zxic/recipes-app/zxic-debug/zxic-debug.bb
+@@ -16,6 +16,8 @@
+ FILESEXTRAPATHS_prepend :="${APP-OPEN-PATH}/platform:"
+ SRC_URI = " \
+ file://zxic_debug \
++ ${@bb.utils.contains("DISTRO_FEATURES", "procd", "file://zxic_debug.init","", d)} \
++ ${@bb.utils.contains("DISTRO_FEATURES", "systemd", "file://zxic_debug.service","", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "sysvinit", "file://zxic_debug.sysvinit","", d)} \
+ "
+
+@@ -37,10 +39,20 @@
+ install -d ${D}${bindir}/
+ install -m 0755 ${S}/zxic_debug/zxic_debug ${D}${bindir}/
+
++ if ${@bb.utils.contains('DISTRO_FEATURES','procd','true','false',d)}; then
++ install -Dm 0755 ${WORKDIR}/zxic_debug.init ${D}${sysconfdir}/init.d/zxic_debug
++ fi
++
++ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
++ install -d ${D}${systemd_unitdir}/system
++ install -m 0644 ${WORKDIR}/zxic_debug.service ${D}${systemd_unitdir}/system
++ fi
++
+ if ${@bb.utils.contains('DISTRO_FEATURES','sysvinit','true','false',d)}; then
+ install -Dm 0755 ${WORKDIR}/zxic_debug.sysvinit ${D}${sysconfdir}/init.d/zxic_debug
+ install -d ${D}${sysconfdir}/rcS.d
+ ln -s ../init.d/zxic_debug ${D}${sysconfdir}/rcS.d/S90zxic_debug
++ ln -s ../init.d/zxic_debug ${D}${sysconfdir}/rcS.d/K10zxic_debug
+ fi
+
+ #install elfs
+@@ -57,5 +69,11 @@
+ #rootfs包含的文件
+ FILES_${PN} = "\
+ ${bindir}/ \
+- ${@bb.utils.contains("DISTRO_FEATURES", "sysvinit", "${sysconfdir}/","", d)} \
++ ${@bb.utils.contains("DISTRO_FEATURES", "procd", "${sysconfdir}/","", d)} \
++ ${@bb.utils.contains("DISTRO_FEATURES", "sysvinit", "${sysconfdir}/","", d)} \
+ "
++SYSTEMD_SERVICE_${PN} = "zxic_debug.service"
++SYSTEMD_AUTO_ENABLE_${PN} = "enable"
++
++
++
+diff --git a/esdk/layers/meta-zxic/recipes-app/zxic-debug/zxic-debug/zxic_debug.service b/esdk/layers/meta-zxic/recipes-app/zxic-debug/zxic-debug/zxic_debug.service
+new file mode 100755
+index 0000000..8dcc30b
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-app/zxic-debug/zxic-debug/zxic_debug.service
+@@ -0,0 +1,11 @@
++[Unit]
++Description=The zxic_debug service
++
++[Service]
++Type=simple
++ExecStart=/usr/bin/zxic_debug
++Restart=always
++
++[Install]
++WantedBy=basic.target
++
+diff --git a/esdk/layers/meta-zxic/recipes-app/zxic-mainctrl/zxic-mainctrl.bb b/esdk/layers/meta-zxic/recipes-app/zxic-mainctrl/zxic-mainctrl.bb
+index dba5672..772f149 100755
+--- a/esdk/layers/meta-zxic/recipes-app/zxic-mainctrl/zxic-mainctrl.bb
++++ b/esdk/layers/meta-zxic/recipes-app/zxic-mainctrl/zxic-mainctrl.bb
+@@ -1,5 +1,5 @@
+ DESCRIPTION = "zxic_mainctrl"
+-DEPENDS = "libnvram libsofttimer libatutils libsoftap openssl libscipc libupi-ab"
++DEPENDS = "libdebug-info libnvram libsofttimer libatutils libsoftap openssl libscipc libupi-ab"
+ SECTION = "app"
+ LICENSE = "zte"
+ PV = "1.0.0"
+@@ -24,6 +24,8 @@
+ S_SRC_PATH = "${S}/zxic_mainctrl"
+ #引用公用头文件和编译选项。
+ include ${BSPDIR}/sources/meta-zxic/conf/app_com.inc
++include ${BSPDIR}/sources/meta-zxic/conf/pub.inc
++CFLAGS_append += "${ZXIC_EXTRA_CFLAGS}"
+
+ #inherit autotools pkgconfig systemd
+
+@@ -74,4 +76,4 @@
+ SYSTEMD_SERVICE_${PN} = "zxic_mainctrl.service"
+ SYSTEMD_AUTO_ENABLE_${PN} = "enable"
+
+-RDEPENDS_${PN} = " libnvram libsofttimer libatutils libsoftap openssl libscipc libupi-ab"
++RDEPENDS_${PN} = " libdebug-info libnvram libsofttimer libatutils libsoftap openssl libscipc libupi-ab"
+diff --git a/esdk/layers/meta-zxic/recipes-core/busybox/busybox/busybox-1.33.1/700-dhcpd-fix.patch b/esdk/layers/meta-zxic/recipes-core/busybox/busybox/busybox-1.33.1/700-dhcpd-fix.patch
+new file mode 100755
+index 0000000..2fff667
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-core/busybox/busybox/busybox-1.33.1/700-dhcpd-fix.patch
+@@ -0,0 +1,80 @@
++--- a/networking/udhcp/dhcpd.c 2024-08-30 18:24:03.164366400 +0800
+++++ b/networking/udhcp/dhcpd.c 2024-08-30 09:21:19.122234100 +0800
++@@ -407,12 +407,16 @@ struct config_keyword {
++ };
++
++ #define OFS(field) offsetof(struct server_data_t, field)
++-
+++static char nv_start[16];
+++static char nv_end[16];
+++static char nv_if[16];
+++static char nv_lease_file[32];
+++static char nv_pidfile[24];
++ static const struct config_keyword keywords[] ALIGN_PTR = {
++ /* keyword handler variable address default */
++- {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"},
++- {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"},
++- {"interface" , read_str , OFS(interface ), "eth0"},
+++ {"start" , udhcp_str2nip , OFS(start_ip ), nv_start},
+++ {"end" , udhcp_str2nip , OFS(end_ip ), nv_end},
+++ {"interface" , read_str , OFS(interface ), nv_if},
++ /* Avoid "max_leases value not sane" warning by setting default
++ * to default_end_ip - default_start_ip + 1: */
++ {"max_leases" , read_u32 , OFS(max_leases ), "235"},
++@@ -421,8 +425,8 @@ static const struct config_keyword keywo
++ {"conflict_time", read_u32 , OFS(conflict_time), "3600"},
++ {"offer_time" , read_u32 , OFS(offer_time ), "60"},
++ {"min_lease" , read_u32 , OFS(min_lease_sec), "60"},
++- {"lease_file" , read_str , OFS(lease_file ), LEASES_FILE},
++- {"pidfile" , read_str , OFS(pidfile ), PID_FILE_PATH "/udhcpd.pid"},
+++ {"lease_file" , read_str , OFS(lease_file ), nv_lease_file},
+++ {"pidfile" , read_str , OFS(pidfile ), nv_pidfile},
++ {"siaddr" , udhcp_str2nip , OFS(siaddr_nip ), "0.0.0.0"},
++ /* keywords with no defaults must be last! */
++ {"option" , read_optset , OFS(options ), ""},
++@@ -433,13 +437,44 @@ static const struct config_keyword keywo
++ {"static_lease" , read_staticlease, OFS(static_leases), ""},
++ };
++ enum { KWS_WITH_DEFAULTS = ARRAY_SIZE(keywords) - 6 };
++-
+++int execute_cmd(const char *cmd, char *out_data, int out_len);
++ static NOINLINE void read_config(const char *file)
++ {
++ parser_t *parser;
++ const struct config_keyword *k;
++ unsigned i;
++ char *token[2];
+++
+++ char value[8] = {0};;
+++ char path[16] = {0};;
+++ if(execute_cmd("nv get gw_in_cap", value, sizeof(value)) == 0
+++ && execute_cmd("nv get path_conf", path, sizeof(path)) == 0){
+++ char option[32] = {0};
+++ char nm[16] = {0};
+++ char gw[16] = {0};
+++ char dns[16] = {0};
+++
+++ execute_cmd("nv get dhcpStart", nv_start, sizeof(nv_start));
+++ execute_cmd("nv get dhcpEnd", nv_end, sizeof(nv_end));
+++ execute_cmd("nv get lan_netmask", nm, sizeof(nm));
+++ if(strcmp(value, "1") == 0){
+++ execute_cmd("nv get lan_name_cap", nv_if, sizeof(nv_if));
+++ execute_cmd("nv get lan_ipaddr_cap", gw, sizeof(gw));
+++ execute_cmd("nv get dhcpDns_cap", dns, sizeof(dns));
+++ }else{
+++ execute_cmd("nv get lan_name", nv_if, sizeof(nv_if));
+++ execute_cmd("nv get lan_ipaddr", gw, sizeof(gw));
+++ execute_cmd("nv get dhcpDns", dns, sizeof(dns));
+++ }
+++ snprintf(nv_lease_file, sizeof(nv_lease_file),"%s/udhcpd.leases",path);
+++ snprintf(nv_pidfile, sizeof(nv_pidfile),"%s/udhcpd.pid",path);
+++ snprintf(option, sizeof(option),"subnet %s",nm);
+++ read_optset(option, (char*)&server_data + OFS(options));
+++ snprintf(option, sizeof(option),"router %s",gw);
+++ read_optset(option, (char*)&server_data + OFS(options));
+++ snprintf(option, sizeof(option),"dns %s",dns);
+++ read_optset(option, (char*)&server_data + OFS(options));
+++ }
++
++ for (i = 0; i < KWS_WITH_DEFAULTS; i++)
++ keywords[i].handler(keywords[i].def, (char*)&server_data + keywords[i].ofs);
+diff --git a/esdk/layers/meta-zxic/recipes-core/busybox/busybox_1.33.1.bb b/esdk/layers/meta-zxic/recipes-core/busybox/busybox_1.33.1.bb
+index a0e8bef..a5a5bf4 100755
+--- a/esdk/layers/meta-zxic/recipes-core/busybox/busybox_1.33.1.bb
++++ b/esdk/layers/meta-zxic/recipes-core/busybox/busybox_1.33.1.bb
+@@ -50,6 +50,7 @@
+ file://busybox-1.33.1/0001-mktemp-add-tmpdir-option.patch \
+ file://busybox-1.33.1/600-dhcpd-fix.patch \
+ file://busybox-1.33.1/0100-zxic-tty-disable-soft-flow-control.patch \
++ file://busybox-1.33.1/700-dhcpd-fix.patch \
+ "
+
+ SRC_URI += "file://busybox-1.33.1/010-syslogd-recive-remote-log.patch"
+@@ -57,7 +58,7 @@
+ #SRC_URI += "file://busybox-1.33.1/022-syslogd-replace-remote-log-facility.patch"
+ SRC_URI += "file://busybox-1.33.1/0100-zxic-add-sync-after-chmod.patch"
+ SRC_URI += "file://busybox-1.33.1/0101-zxic-bb_get_chunk_from_file-limit-10MB.patch"
+-#SRC_URI += "file://busybox-1.33.1/0102-zxic-ash-read-etc-profile.patch"
++SRC_URI += "file://busybox-1.33.1/0102-zxic-ash-read-etc-profile.patch"
+ SRC_URI += "file://busybox-1.33.1/0103-top-short-lived-processes-optimize.patch"
+ SRC_URI += "file://busybox-1.33.1/0103-syslogd-data-encryption.patch"
+
+diff --git a/esdk/layers/meta-zxic/recipes-core/glibc/files/0002-fix-y2038-time_t-unsigned-long.patch b/esdk/layers/meta-zxic/recipes-core/glibc/files/0002-fix-y2038-time_t-unsigned-long.patch
+new file mode 100755
+index 0000000..bc67008
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-core/glibc/files/0002-fix-y2038-time_t-unsigned-long.patch
+@@ -0,0 +1,48 @@
++diff -ruN a/bits/typesizes.h b/bits/typesizes.h
++--- a/bits/typesizes.h 2024-05-13 15:49:06.279310297 +0800
+++++ b/bits/typesizes.h 2024-06-24 19:10:05.732039157 +0800
++@@ -47,7 +47,7 @@
++ #define __FSWORD_T_TYPE __SWORD_TYPE
++ #define __ID_T_TYPE __U32_TYPE
++ #define __CLOCK_T_TYPE __SLONGWORD_TYPE
++-#define __TIME_T_TYPE __SLONGWORD_TYPE
+++#define __TIME_T_TYPE __ULONGWORD_TYPE
++ #define __USECONDS_T_TYPE __U32_TYPE
++ #define __SUSECONDS_T_TYPE __SLONGWORD_TYPE
++ #define __DADDR_T_TYPE __S32_TYPE
++diff -ruN a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c
++--- a/sysdeps/unix/sysv/linux/adjtime.c 2024-05-13 15:49:08.415312000 +0800
+++++ b/sysdeps/unix/sysv/linux/adjtime.c 2024-06-26 16:25:56.512216926 +0800
++@@ -33,16 +33,17 @@
++ struct timeval tmp;
++
++ /* We will do some check here. */
++- tmp.tv_sec = itv->tv_sec + itv->tv_usec / 1000000L;
+++ tmp.tv_sec = (signed long)itv->tv_sec + itv->tv_usec / 1000000L;
++ tmp.tv_usec = itv->tv_usec % 1000000L;
++- if (tmp.tv_sec > MAX_SEC || tmp.tv_sec < MIN_SEC)
+++ if ((signed long)tmp.tv_sec > (signed long)MAX_SEC || (signed long)tmp.tv_sec < (signed long)MIN_SEC)
++ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
++- tntx.offset = tmp.tv_usec + tmp.tv_sec * 1000000L;
+++ tntx.offset = tmp.tv_usec + (signed long)tmp.tv_sec * 1000000L;
++ tntx.modes = ADJ_OFFSET_SINGLESHOT;
++ }
++ else
++ tntx.modes = ADJ_OFFSET_SS_READ;
++
+++
++ if (__glibc_unlikely (__adjtimex (&tntx) < 0))
++ return -1;
++
++diff -ruN a/sysdeps/unix/sysv/linux/generic/bits/typesizes.h b/sysdeps/unix/sysv/linux/generic/bits/typesizes.h
++--- a/sysdeps/unix/sysv/linux/generic/bits/typesizes.h 2024-05-13 15:49:08.427312010 +0800
+++++ b/sysdeps/unix/sysv/linux/generic/bits/typesizes.h 2024-06-24 19:10:56.580110887 +0800
++@@ -48,7 +48,7 @@
++ #define __FSWORD_T_TYPE __SWORD_TYPE
++ #define __ID_T_TYPE __U32_TYPE
++ #define __CLOCK_T_TYPE __SLONGWORD_TYPE
++-#define __TIME_T_TYPE __SLONGWORD_TYPE
+++#define __TIME_T_TYPE __ULONGWORD_TYPE
++ #define __USECONDS_T_TYPE __U32_TYPE
++ #define __SUSECONDS_T_TYPE __SLONGWORD_TYPE
++ #define __DADDR_T_TYPE __S32_TYPE
+diff --git a/esdk/layers/meta-zxic/recipes-core/glibc/glibc_%.bbappend b/esdk/layers/meta-zxic/recipes-core/glibc/glibc_%.bbappend
+index 0314602..1ea730c 100755
+--- a/esdk/layers/meta-zxic/recipes-core/glibc/glibc_%.bbappend
++++ b/esdk/layers/meta-zxic/recipes-core/glibc/glibc_%.bbappend
+@@ -3,6 +3,7 @@
+
+ SRC_URI += " \
+ file://0001-write-log-to-zcat-tool.patch \
++ file://0002-fix-y2038-time_t-unsigned-long.patch \
+ "
+
+ do_install_append() {
+diff --git a/esdk/layers/meta-zxic/recipes-devtools/python/python3/0001-zxic-y2038-time_t.patch b/esdk/layers/meta-zxic/recipes-devtools/python/python3/0001-zxic-y2038-time_t.patch
+new file mode 100755
+index 0000000..6740344
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-devtools/python/python3/0001-zxic-y2038-time_t.patch
+@@ -0,0 +1,35 @@
++From 0a7fc505937e81c1ff9ce19f4a0084d4f7040cf3 Mon Sep 17 00:00:00 2001
++From: =?utf-8?q?=E5=91=A8=E5=9B=BD=E5=9D=A10318000136?=
++ <zhou.guopo@sanechips.com.cn>
++Date: Mon, 9 Sep 2024 16:02:36 +0800
++Subject: [PATCH] zxic y2038 time_t
++
++---
++ Modules/timemodule.c | 4 ++--
++ 1 file changed, 2 insertions(+), 2 deletions(-)
++
++diff --git a/Modules/timemodule.c b/Modules/timemodule.c
++index 096911d..b34bf54 100644
++--- a/Modules/timemodule.c
+++++ b/Modules/timemodule.c
++@@ -1556,7 +1556,7 @@ get_zone(char *zone, int n, struct tm *p)
++ #endif
++ }
++
++-static time_t
+++static long
++ get_gmtoff(time_t t, struct tm *p)
++ {
++ #ifdef HAVE_STRUCT_TM_TM_ZONE
++@@ -1630,7 +1630,7 @@ init_timezone(PyObject *m)
++ static const time_t YEAR = (365 * 24 + 6) * 3600;
++ time_t t;
++ struct tm p;
++- time_t janzone_t, julyzone_t;
+++ long janzone_t, julyzone_t;
++ char janname[10], julyname[10];
++ t = (time((time_t *)0) / YEAR) * YEAR;
++ _PyTime_localtime(t, &p);
++--
++2.17.1
++
+diff --git a/esdk/layers/meta-zxic/recipes-devtools/python/python3_3.8.%.bbappend b/esdk/layers/meta-zxic/recipes-devtools/python/python3_3.8.%.bbappend
+new file mode 100755
+index 0000000..8c97d91
+--- /dev/null
++++ b/esdk/layers/meta-zxic/recipes-devtools/python/python3_3.8.%.bbappend
+@@ -0,0 +1,5 @@
++
++FILESEXTRAPATHS_prepend := "${THISDIR}/python3:"
++
++SRC_URI += "file://0001-zxic-y2038-time_t.patch"
++
+diff --git a/esdk/layers/meta-zxic/recipes-kernel/linux-libc-headers/linux-libc-headers/0001-add-zxic-volte_drv.h.patch b/esdk/layers/meta-zxic/recipes-kernel/linux-libc-headers/linux-libc-headers/0001-add-zxic-volte_drv.h.patch
+index 96ec3d0..af2471f 100755
+--- a/esdk/layers/meta-zxic/recipes-kernel/linux-libc-headers/linux-libc-headers/0001-add-zxic-volte_drv.h.patch
++++ b/esdk/layers/meta-zxic/recipes-kernel/linux-libc-headers/linux-libc-headers/0001-add-zxic-volte_drv.h.patch
+@@ -1,20 +1,19 @@
+-From b1b616e6daa86e3000de9eb74b54290ad47b8b4e Mon Sep 17 00:00:00 2001
+-From: =?utf-8?q?=E5=91=A8=E5=9B=BD=E5=9D=A1=2010053386?=
+- <zhou.guopo@zte.com.cn>
+-Date: Mon, 13 Mar 2023 15:43:40 +0800
+-Subject: [PATCH] add zxic volte_drv.h
++From 8f9f5fc32b4cdb448aaf62e1fb56dfb63af570fd Mon Sep 17 00:00:00 2001
++From: =?UTF-8?q?=E5=BE=90=E6=96=B0=E5=BC=BA?= <xu.xinqiang@sanechips.com.cn>
++Date: Fri, 23 Aug 2024 13:42:50 +0800
++Subject: [PATCH] volte drv
+
+ ---
+- include/uapi/linux/volte_drv.h | 112 +++++++++++++++++++++++++++++++++
+- 1 file changed, 112 insertions(+)
+- create mode 100644 include/uapi/linux/volte_drv.h
++ include/uapi/linux/volte_drv.h | 154 +++++++++++++++++++++++++++++++++
++ 1 file changed, 154 insertions(+)
++ create mode 100755 include/uapi/linux/volte_drv.h
+
+ diff --git a/include/uapi/linux/volte_drv.h b/include/uapi/linux/volte_drv.h
+-new file mode 100644
+-index 0000000..010d9ac
++new file mode 100755
++index 0000000..7862449
+ --- /dev/null
+ +++ b/include/uapi/linux/volte_drv.h
+-@@ -0,0 +1,112 @@
++@@ -0,0 +1,154 @@
+ +/*
+ + * Copyright (C) 2013 ZTE, China
+ + *
+@@ -26,6 +25,9 @@
+ +#define __LINUX_VOLTE_DRV_H
+ +
+ +#include <linux/ioctl.h>
+++#include <linux/types.h>
+++
+++
+ +
+ +typedef enum {
+ + VOICE_GSM_MODE = 0,
+@@ -76,6 +78,13 @@
+ +} T_Codec_Path;
+ +
+ +typedef enum {
+++ NOR_VOICE_INF_MODE = 0,//normal
+++ VB_VOICE_INF_MODE,//voice buffer
+++ MAX_VOICE_INF_MODE
+++} T_VoiceInfMode;
+++
+++
+++typedef enum {
+ + VOICE_STOP = 0,
+ + VOICE_START,
+ + MAX_VOICE_STATE
+@@ -90,6 +99,15 @@
+ +
+ +} T_Voice_Para;
+ +
+++typedef struct {
+++ uint32_t fs; //8000;16000
+++ uint32_t enable; //// 0 disable;1 enable
+++ uint32_t type;//0 single core;1 mult core
+++
+++
+++} T_VoiceBuf_Para;
+++
+++
+ +#ifdef __KERNEL__
+ +struct voice_dev {
+ + T_Voice_Para param;
+@@ -102,6 +120,29 @@
+ +#define VOICE_IOCTL_GET_SLIC_USE_FLAG _IOR ('v', 12, int)
+ +#define VOICE_IOCTL_VPLOOP _IOW('v', 13, int)
+ +
+++#define VOICE_IOCTL_SET_VOL _IOW('v', 14, int)
+++#define VOICE_IOCTL_GET_VOL _IOR('v', 15, int)
+++
+++#define VOICE_IOCTL_SET_MUTE _IOW('v', 16, bool)
+++#define VOICE_IOCTL_GET_MUTE _IOR('v', 17, bool)
+++
+++#define VOICE_IOCTL_SET_PATH _IOW('v', 18, int)
+++#define VOICE_IOCTL_GET_PATH _IOR('v', 19, int)
+++
+++#define VOICE_IOCTL_GET_FS _IOR('v', 20, int)
+++#define VOICE_IOCTL_SET_VOICE_NVRW _IOW('v', 21, int)
+++
+++#define VOICE_IOCTL_SET_VP _IOW('v', 22, int)
+++#define VOICE_IOCTL_GET_VP _IOR('v', 23, int)
+++
+++#define VOICE_IOCTL_SET_VBUF _IOW('v', 24, T_VoiceBuf_Para)
+++#define VOICE_IOCTL_GET_VBUF _IOR('v', 25, T_VoiceBuf_Para)
+++
+++#define VOICE_IOCTL_SET_INF_MODE _IOW('v', 26, int)
+++#define VOICE_IOCTL_GET_INF_MODE _IOR('v', 27, int)
+++
+++
+++
+ +#ifdef __KERNEL__
+ +#define print_audio(fmt, ...) \
+ + printk(fmt, ##__VA_ARGS__)
+@@ -128,5 +169,5 @@
+ +#endif
+ +
+ --
+-2.17.1
++2.25.1
+
+diff --git a/esdk/layers/meta-zxic/recipes-kernel/linux/files/zx297520v3/linux-5_10-vehicle_dc_ref-normal-defconfig b/esdk/layers/meta-zxic/recipes-kernel/linux/files/zx297520v3/linux-5_10-vehicle_dc_ref-normal-defconfig
+index ef22244..9baa954 100755
+--- a/esdk/layers/meta-zxic/recipes-kernel/linux/files/zx297520v3/linux-5_10-vehicle_dc_ref-normal-defconfig
++++ b/esdk/layers/meta-zxic/recipes-kernel/linux/files/zx297520v3/linux-5_10-vehicle_dc_ref-normal-defconfig
+@@ -156,7 +156,9 @@
+ CONFIG_SIGNALFD=y
+ CONFIG_TIMERFD=y
+ CONFIG_EVENTFD=y
+-# CONFIG_SHMEM is not set
++#l.yang modify for mount to limit size
++CONFIG_SHMEM=y
++#l.yang modify for mount to limit size
+ CONFIG_AIO=y
+ CONFIG_IO_URING=y
+ CONFIG_ADVISE_SYSCALLS=y
+@@ -2232,12 +2234,12 @@
+ # end of Microsoft Hyper-V guest support
+
+ # CONFIG_GREYBUS is not set
+-# CONFIG_STAGING is not set
+-#
++CONFIG_STAGING=y
++# CONFIG_VOICE_DRV is not set
+ # ZX297520 voice buffer driver
+ #
+-# CONFIG_VOICE_BUFFER_DRV is not set
+-# CONFIG_VBUFF_IN_MULTI_CORE is not set
++CONFIG_VOICE_BUFFER_DRV=y
++CONFIG_VBUFF_IN_MULTI_CORE=y
+ # CONFIG_GOLDFISH is not set
+ # CONFIG_CHROME_PLATFORMS is not set
+ # CONFIG_MELLANOX_PLATFORM is not set
+@@ -2491,6 +2493,12 @@
+ # CONFIG_PROC_CHILDREN is not set
+ CONFIG_KERNFS=y
+ CONFIG_SYSFS=y
++#l.yang modify for mount to limit size
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++CONFIG_TMPFS_XATTR=y
++CONFIG_MEMFD_CREATE=y
++#l.yang modify for mount to limit size
+ # CONFIG_CONFIGFS_FS is not set
+ # end of Pseudo filesystems
+
+diff --git a/esdk/layers/meta-zxic/recipes-kernel/linux/linux-zxic_5.10.bb b/esdk/layers/meta-zxic/recipes-kernel/linux/linux-zxic_5.10.bb
+index a8c7f65..5b2cc6d 100755
+--- a/esdk/layers/meta-zxic/recipes-kernel/linux/linux-zxic_5.10.bb
++++ b/esdk/layers/meta-zxic/recipes-kernel/linux/linux-zxic_5.10.bb
+@@ -12,7 +12,7 @@
+ DEPENDS += "${@bb.utils.contains('DISTRO_FEATURES','dm-verity','zstd-native','',d)}"
+ inherit kernel siteinfo
+
+-EXTRA_OEMAKE_append = " LOADADDR=${KERNEL_LOADADDR} EXTRA_CFLAGS='${ZXIC_EXTRA_CFLAGS}' "
++EXTRA_OEMAKE_append = " LOADADDR=${KERNEL_LOADADDR} EXTRA_CFLAGS='${ZXIC_EXTRA_CFLAGS}' EXTRA_AFLAGS='${ZXIC_EXTRA_CFLAGS}' "
+ FILESEXTRAPATHS_prepend :="${TOPDIR}/../upstream:"
+ # PR_CONFIG_cpe = "linux-5_10-cpe-${BOOT_CTL}-defconfig"
+ # PR_CONFIG_v2x = "linux-5_10-v2x-${BOOT_CTL}-defconfig"
+diff --git a/esdk/layers/meta-zxic/recipes-kernel/linux/linux_bb.diff b/esdk/layers/meta-zxic/recipes-kernel/linux/linux_bb.diff
+index 34dda2f..f2f6434 100755
+--- a/esdk/layers/meta-zxic/recipes-kernel/linux/linux_bb.diff
++++ b/esdk/layers/meta-zxic/recipes-kernel/linux/linux_bb.diff
+@@ -16,7 +16,7 @@
+ DEPENDS += "${@bb.utils.contains('DISTRO_FEATURES','dm-verity','zstd-native','',d)}"
+ inherit kernel siteinfo
+
+- EXTRA_OEMAKE_append = " LOADADDR=${KERNEL_LOADADDR} EXTRA_CFLAGS='${ZXIC_EXTRA_CFLAGS}' "
++ EXTRA_OEMAKE_append = " LOADADDR=${KERNEL_LOADADDR} EXTRA_CFLAGS='${ZXIC_EXTRA_CFLAGS}' EXTRA_AFLAGS='${ZXIC_EXTRA_CFLAGS}' "
+ -FILESEXTRAPATHS_prepend :="${SRC-PATH}:"
+ +FILESEXTRAPATHS_prepend :="${TOPDIR}/../upstream:"
+ # PR_CONFIG_cpe = "linux-5_10-cpe-${BOOT_CTL}-defconfig"
+diff --git a/upstream/linux-5.10/arch/arm/kernel/svc_s.S b/upstream/linux-5.10/arch/arm/kernel/svc_s.S
+index a52abb7..f249292 100755
+--- a/upstream/linux-5.10/arch/arm/kernel/svc_s.S
++++ b/upstream/linux-5.10/arch/arm/kernel/svc_s.S
+@@ -1,9 +1,12 @@
+
++#define _USE_VEHICLE_DC
++#include "ram_base_config_7520v3.h"
++
+ #define GIC_DIST_BASE (0xF2000000)
+ #define GIC_RDIST_BASE (0xF2040000)
+
+ #define REAL_TXT_ADDR (CONFIG_PHYS_OFFSET + 0x8000)
+-#define DTB_ADDR (CONFIG_DTB_ADDR)
++#define DTB_ADDR (DDR_BASE_CAP_DTB_ADDR)
+
+ secure_init:
+
+diff --git a/upstream/linux-5.10/drivers/dma/sc/zx297520v3_dma.c b/upstream/linux-5.10/drivers/dma/sc/zx297520v3_dma.c
+index 6ef00d8..6eb68fa 100755
+--- a/upstream/linux-5.10/drivers/dma/sc/zx297520v3_dma.c
++++ b/upstream/linux-5.10/drivers/dma/sc/zx297520v3_dma.c
+@@ -1090,7 +1090,7 @@
+ /* schedule tasklet on this channel */
+ /* yu.dong@20240617 [T106BUG-641] SPI packet loss issue, increase kernel buffer and read all cached data away, no data loss start */
+ #ifdef _USE_VEHICLE_DC || _USE_VEHICLE_DC_REF
+- if((channel_id == DMA_CH_UART0_RX) || (channel_id == DMA_CH_UART2_RX) || (channel_id == DMA_CH_SSP0_RX)){
++ if((channel_id == DMA_CH_UART0_RX) || (channel_id == DMA_CH_UART2_RX)||(channel_id == DMA_CH_SSP0_RX)||(channel_id == DMA_CH_SSP1_RX)){
+ if (dmac_ptr->dma_chan[channel_id].desc.callback)
+ dmac_ptr->dma_chan[channel_id].desc.callback(dmac_ptr->dma_chan[channel_id].desc.callback_param);
+ }else
+diff --git a/upstream/linux-5.10/drivers/misc/zcat/debug_info.c b/upstream/linux-5.10/drivers/misc/zcat/debug_info.c
+index d23e340..52a2146 100755
+--- a/upstream/linux-5.10/drivers/misc/zcat/debug_info.c
++++ b/upstream/linux-5.10/drivers/misc/zcat/debug_info.c
+@@ -5,10 +5,7 @@
+ #include <linux/cdev.h>
+ #include <linux/semaphore.h>
+ #include <linux/timer.h>
+-
+-// #include <linux/fs.h>
+ #include <linux/ioport.h>
+-// #include <linux/serial_reg.h>
+ #include <linux/poll.h>
+ #include <linux/delay.h>
+ #include <linux/wait.h>
+@@ -18,88 +15,94 @@
+ #include <linux/types.h>
+ #include <linux/device.h>
+ #include <linux/miscdevice.h>
+-// #include <linux/spinlock.h>
+ #include <linux/list.h>
+ #include <linux/slab.h>
+ #include <linux/sched.h>
+-// #include <linux/kthread.h>
+ #include <asm/io.h>
+-
+ #include <linux/vmalloc.h>
+ #include <linux/soc/zte/rpmsg.h>
+-// #include <linux/syscalls.h>
+-
+-// #include "debuginfo.h"
+ #include "pub_debug_info.h"
+ #include "ringbuf.h"
++#include "ram_config.h"
++#include "ZspTrace.h"
++#include <linux/proc_fs.h>
++#include <asm/barrier.h>
++#include <asm/cache.h>
++#include <asm/cacheflush.h>
++#include <linux/seq_file.h>
++#include <linux/ktime.h>
++#include <linux/time.h>
+
+-
+-#if defined(_USE_ZXIC_DEBUG_INFO) && !defined(CONFIG_SYSTEM_RECOVERY)
++#if defined(_USE_ZXIC_DEBUG_INFO)
+ /*******************************************************************************
+ * 宏定义 *
+ *******************************************************************************/
+-#define DEBUG_INFO_SHARE_MEM_LEN (0x2000)
++#define DEBUG_INFO_AP_MEM_LEN (0x2000)
+ #define DEBUG_INFO_READABLE_LEN (0x1400)
+-#define DEBUG_INFO_MAX_DATA_LEN (128)
+-#define DEBUG_INFO_MAX_TOTAL_LEN (140) // 8 + 128 + 4
+ #define DEBUG_INFO_READ_TIME_MSECS (10000)
+
+-#define DEBUG_INFO_CHANNEL (9)
+-#define DEBUG_INFO_MSG_CAP_SIZE (2 * 1024)
+-
+ #define DEBUG_INFO_OK (0)
+ #define DEBUG_INFO_ERROR (-1)
++#define DEBUG_READ_NOBLOCK (11)
+
+-#define DEBUG_INFO_IOCTL_SET_DISABLE (0x1001)
++#define DEBUG_INFO_MAX_ID_LEN (16+3)
++#define DEBUG_INFO_MAX_DATA_LEN (128)
++#define DEBUG_INFO_MAX_TIME_LEN (0)//(20+3)
++#define DEBUG_INFO_MAX_DATE_LEN (19+3)
++#define DEBUG_INFO_MAX_TOTAL_LEN (DEBUG_INFO_MAX_ID_LEN + DEBUG_INFO_MAX_DATA_LEN + DEBUG_INFO_MAX_TIME_LEN)
++
++#define DEBUG_INFO_CORE_NUM (2)
+
+ /*******************************************************************************
+ * 结构体定义 *
+ *******************************************************************************/
+-typedef unsigned int UINT32;
++typedef unsigned int UINT32;
+ typedef unsigned short UINT16;
+-typedef unsigned char UINT8;
+-
+-typedef struct
+-{
+- UINT16 module_id; // 模块id
+- UINT16 sub_len; // 用户数据长度
+- UINT32 time;
+- char sub_data[]; // 用户数据
+-} T_SHARED_MEM_DATA;
+-
+-typedef struct
+-{
+- UINT32 head; // 0x010a0a0a
+- UINT32 total_len; // 数据内容长度
+- long long time; // time()函数获取
++typedef unsigned char UINT8;
++typedef unsigned long UINT64;
++typedef struct{
++ unsigned int head; /* 0x010a0a0a */
++ unsigned int datalen[DEBUG_INFO_CORE_NUM]; /* 数据内容长度 */
+ } T_SAVE_FILE_DATA;
+
+ /*******************************************************************************
+ * 全局变量 *
+ *******************************************************************************/
+-volatile T_RINGBUFFER *g_debug_info_buf = NULL;
+ static struct semaphore debug_sem;
+-static DEFINE_RAW_SPINLOCK(debugWr_lock);
+ static int g_init_flag = 0;
++UINT32 *g_ps_debug_write_cnt;
++UINT32 *g_ps_debug_full_cnt;
++UINT32 g_ps_debug_read_cnt;
++UINT32 g_ps_debug_read_full_cnt;
++unsigned long g_debug_read_cnt;
++unsigned long g_ap_debug_write_cnt;
++unsigned long g_ap_debug_read_cnt;
++UINT8 *g_ap_debug_buffer_start;
++UINT8 *g_ap_debug_buffer_read;
++UINT8 *g_ap_debug_buffer_write;
++UINT8 *g_ap_debug_buffer_end;
++UINT8 *g_ps_debug_buffer_start;
++UINT8 *g_ps_debug_buffer_end;
++UINT8 *g_ps_debug_buffer_read;
++static DEFINE_SPINLOCK(debug_info_lock);
++static char g_ap_debug_buffer[DEBUG_INFO_AP_MEM_LEN];
++unsigned long g_debug_read_state = 0;
+
+ /*******************************************************************************
+ * 内部函数定义 *
+ *******************************************************************************/
+-static int sc_debug_info_read_to_user(char *buf, unsigned short count);
+-static int sc_debug_info_record_from_user(const char *info, unsigned short count);
+-static int sc_debug_info_write(UINT32 flag, const UINT8 *buf, UINT32 len);
+-static void sc_debug_info_from_ap(void *buf, unsigned int len);
+-
++static int sc_debug_info_read_to_user(char *buf, size_t count);
++static int sc_debug_info_record_from_user(const char *info, size_t count);
++static void sc_debug_info_from_ps(void *buf, unsigned int len);
+ static void kernel_timer_timeout(struct timer_list *t);
+ static ssize_t debug_info_read(struct file *fp, char __user *buf, size_t count, loff_t *pos);
+ static ssize_t debug_info_write(struct file *fp, const char __user *buf, size_t count, loff_t *pos);
+ static int debug_info_open(struct inode *ip, struct file *fp);
+ static long debug_info_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
+ static int debug_info_release(struct inode *ip, struct file *fp);
+-
+-//初始化timer
++extern u64 cop_time_get_value64(void);
++extern int seq_write(struct seq_file *seq, const void *data, size_t len);
+ static DEFINE_TIMER(timer, kernel_timer_timeout);
+-
+ static const struct file_operations debug_info_fops = {
+ .owner = THIS_MODULE,
+ .read = debug_info_read,
+@@ -114,35 +117,36 @@
+ .name = "debug_info",
+ .fops = &debug_info_fops,
+ };
+-
+ static void kernel_timer_timeout(struct timer_list *t)
+-{
++{
+ if (debug_sem.count == 0)
+- {
++ {
+ up(&debug_sem);
+ }
+- /* 因为内核定时器是一个单次的定时器,所以如果想要多次重复定时需要在定时器绑定的函数结尾重新装载时间,并启动定时 */
+ /* Kernel Timer restart */
+- mod_timer(&timer, jiffies + msecs_to_jiffies(DEBUG_INFO_READ_TIME_MSECS));
++ mod_timer(&timer, jiffies + msecs_to_jiffies(DEBUG_INFO_READ_TIME_MSECS));
+ }
+
++/* Started by AICoder, pid:y6ffbg9a06ieda114a190b4cb0ff4417bd78c0f4 */
+ static ssize_t debug_info_read(struct file *fp, char __user *buf, size_t count, loff_t *pos)
+ {
+ int ret;
+ int rd_len;
+
+- ret = down_interruptible(&debug_sem);
+- if(ret < 0)
++ if (g_debug_read_state != DEBUG_READ_NOBLOCK)
+ {
+- return ret;
++ ret = down_interruptible(&debug_sem);
++ if (ret < 0)
++ {
++ return ret;
++ }
+ }
+- else
+- {
+- rd_len = sc_debug_info_read_to_user(buf, count);
+- }
++
++ rd_len = sc_debug_info_read_to_user(buf, count);
+
+ return rd_len;
+ }
++/* Ended by AICoder, pid:y6ffbg9a06ieda114a190b4cb0ff4417bd78c0f4 */
+
+ static ssize_t debug_info_write(struct file *fp, const char __user *buf, size_t count, loff_t *pos)
+ {
+@@ -156,241 +160,425 @@
+ return 0;
+ }
+
+-static long debug_info_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
+-{
+- switch(cmd)
+- {
+- case DEBUG_INFO_IOCTL_SET_DISABLE:
+- *(volatile UINT32 *)ZCAT_DEBUG_INFO_DISABLE = arg;
+- break;
+-
+- default:
+- break;
++/* Started by AICoder, pid:u635ed463ce5ab2145a109c3c0f54d149e6386b3 */
++static long debug_info_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) {
++ if (cmd == DEBUG_READ_NOBLOCK) {
++ g_debug_read_state = DEBUG_READ_NOBLOCK;
++ } else {
++ // 如果命令不匹配,返回错误码
++ return -EINVAL;
+ }
++
++ // 记录调试信息
++ sc_debug_info_record("debug_info", "read noblock!\n");
++
+ return 0;
+ }
++/* Ended by AICoder, pid:u635ed463ce5ab2145a109c3c0f54d149e6386b3 */
+
+ static int debug_info_release(struct inode *ip, struct file *fp)
+ {
+ return 0;
+ }
+
+-static void sc_debug_info_from_ap(void *buf, unsigned int len)
++static int ap_log_proc_show(struct seq_file *m, void *v)
+ {
+- T_SHARED_MEM_DATA *debug_msg = (T_SHARED_MEM_DATA *)buf;
+- debug_msg->time = jiffies;
++ unsigned long writecnt = g_ap_debug_write_cnt;
+
+- sc_debug_info_write(ZCAT_MEM_TYPE_KERNEL, buf, len);
++ if (writecnt > DEBUG_INFO_AP_MEM_LEN)
++ {
++ writecnt = DEBUG_INFO_AP_MEM_LEN;
++ }
++
++ seq_write(m, g_ap_debug_buffer_start, writecnt);
++
++ return 0;
++}
++
++static int ps_log_proc_show(struct seq_file *m, void *v)
++{
++ unsigned long writecnt = 0;
++ unsigned long fulllcnt = 0;
++
++ writecnt = *(UINT32 *)g_ps_debug_write_cnt;
++ fulllcnt = *(UINT32 *)g_ps_debug_full_cnt;
++
++ if (fulllcnt > 0)
++ {
++ writecnt = PS_DEBUG_INFO_SIZE;
++ }
++
++ //__inval_dcache_area((void *)g_ps_debug_buffer_start, writecnt);
++ seq_write(m, g_ps_debug_buffer_start, writecnt);
++
++ return 0;
++}
++
++UINT32 skip_end_null(char *buf, size_t count)
++{
++ UINT32 len = 0;
++ char *tmpbuf = buf;
++
++ while (count > 0)
++ {
++ if (*tmpbuf == '\0')
++ {
++ ++len;
++ tmpbuf -= 1;
++ count -= 1;
++ }
++ else
++ {
++ break;
++ }
++ }
++
++ return len;
++}
++
++int sc_debug_info_read_ap(char *buf, size_t count)
++{
++ UINT32 readLen = 0;
++ UINT32 updatelen = 0;
++ UINT32 readremainLen = 0;
++ UINT8 *readbuffaddr = 0;
++ UINT32 nullLen = 0;
++ char *tmpbuf = buf;
++
++ updatelen = g_ap_debug_write_cnt - g_ap_debug_read_cnt;
++ if (updatelen > DEBUG_INFO_AP_MEM_LEN)
++ updatelen = DEBUG_INFO_AP_MEM_LEN;
++
++ if(g_ap_debug_buffer_end - g_ap_debug_buffer_read >= updatelen)
++ {
++ readbuffaddr = g_ap_debug_buffer_read;
++ readLen = updatelen;
++ if (copy_to_user(tmpbuf , readbuffaddr, readLen))
++ {
++ return -EFAULT;
++ }
++ g_ap_debug_buffer_read += readLen;
++ }
++ else if(g_ap_debug_buffer_end - g_ap_debug_buffer_read < updatelen)
++ {
++ readbuffaddr = g_ap_debug_buffer_read;
++ readLen = g_ap_debug_buffer_end - readbuffaddr;
++ readremainLen = updatelen - readLen;
++ nullLen = skip_end_null(g_ap_debug_buffer_end - 1, readLen);
++ readLen = readLen - nullLen;
++ if (copy_to_user(tmpbuf, readbuffaddr, readLen))
++ {
++ return -EFAULT;
++ }
++ if (copy_to_user(tmpbuf + readLen, g_ap_debug_buffer_start, readremainLen))
++ {
++ return -EFAULT;
++ }
++ g_ap_debug_buffer_read = g_ap_debug_buffer_start + readremainLen;
++ }
++ else
++ {
++ panic("gaohf sc_debug_info_read_to_user error");
++ }
++ g_ap_debug_read_cnt = g_ap_debug_write_cnt;
++
++ return (readLen + readremainLen);
++}
++
++int sc_debug_info_read_ps(char *buf, size_t count)
++{
++ UINT32 readLen = 0;
++ UINT32 readremainLen = 0;
++ UINT8 *readbuffaddr = 0;
++ UINT32 fulllcnt = 0;
++ UINT32 fulllcntdiff = 0;
++ unsigned long writecnt = 0;
++ UINT32 nullLen = 0;
++ char *tmpbuf = buf;
++
++ writecnt = *(volatile UINT32 *)g_ps_debug_write_cnt;
++ fulllcnt = *(volatile UINT32 *)g_ps_debug_full_cnt;
++
++ if (fulllcnt >= g_ps_debug_read_full_cnt)
++ {
++ fulllcntdiff = fulllcnt - g_ps_debug_read_full_cnt;
++ }
++ else
++ {
++ fulllcntdiff = 0xFFFFFFFF - g_ps_debug_read_full_cnt + fulllcnt;
++ }
++ if(fulllcntdiff >= 2)
++ {
++ readbuffaddr = g_ps_debug_buffer_start + writecnt;
++ readLen = g_ps_debug_buffer_end - readbuffaddr;
++ readremainLen = writecnt;
++ nullLen = skip_end_null(g_ps_debug_buffer_end - 1, readLen);
++ readLen = readLen - nullLen;
++ if (copy_to_user(tmpbuf, readbuffaddr, readLen))
++ {
++ return -EFAULT;
++ }
++ if (copy_to_user(tmpbuf + readLen, g_ps_debug_buffer_start, readremainLen))
++ {
++ return -EFAULT;
++ }
++ g_ps_debug_buffer_read = g_ps_debug_buffer_start + readremainLen;
++ }
++ else if(fulllcntdiff == 0)
++ {
++ readbuffaddr = g_ps_debug_buffer_read;
++ readLen = writecnt - g_ps_debug_read_cnt;;
++ if (copy_to_user(tmpbuf , readbuffaddr, readLen))
++ {
++ return -EFAULT;
++ }
++ g_ps_debug_buffer_read += readLen;
++ }
++ else if(fulllcntdiff == 1)
++ {
++ readLen = writecnt >= g_ps_debug_read_cnt ? writecnt : g_ps_debug_read_cnt;
++ readLen = PS_DEBUG_INFO_SIZE - readLen;
++ readbuffaddr = g_ps_debug_buffer_read;
++ nullLen = skip_end_null(g_ps_debug_buffer_end - 1, readLen);
++ readLen = readLen - nullLen;
++ if (copy_to_user(tmpbuf, readbuffaddr, readLen))
++ {
++ return -EFAULT;
++ }
++ readremainLen = writecnt;
++ if (copy_to_user(tmpbuf + readLen , g_ps_debug_buffer_start, readremainLen))
++ {
++ return -EFAULT;
++ }
++ g_ps_debug_buffer_read = g_ps_debug_buffer_start + readremainLen;
++ }
++ else
++ {
++ panic("gaohf sc_debug_info_read_to_user error");
++ }
++ g_ps_debug_read_cnt = writecnt;
++ g_ps_debug_read_full_cnt = fulllcnt;
++
++ return (readLen + readremainLen);
++}
++
++int sc_debug_info_read_to_user(char *buf, size_t count)
++{
++ char *tmpbuf = 0;
++ int ret = 0;
++ int ap_len = 0;
++ int ps_len = 0;
++ T_SAVE_FILE_DATA fileDataHead;
++
++ if (g_init_flag == 0)
++ {
++ printk("debug_info not init.\n");
++ return DEBUG_INFO_ERROR;
++ }
++
++ if (count == 0 || buf == NULL )
++ {
++ printk("sc_debug_info_read_to_user count == 0 || buf == NULL \n");
++ return DEBUG_INFO_ERROR;
++ }
++ tmpbuf = buf + sizeof(T_SAVE_FILE_DATA);
++ ap_len = sc_debug_info_read_ap(tmpbuf, DEBUG_INFO_AP_MEM_LEN);
++ tmpbuf += ap_len;
++ ps_len = sc_debug_info_read_ps(tmpbuf, PS_DEBUG_INFO_SIZE);
++
++ fileDataHead.head = 0x010a0a0a;
++ fileDataHead.datalen[0] = ap_len;
++ fileDataHead.datalen[1] = ps_len;
++
++ if (copy_to_user(buf, &fileDataHead, sizeof(T_SAVE_FILE_DATA)))
++ {
++ printk("sc_debug_info_read_to_user copy_to_user error \n");
++ return -EFAULT;
++ }
++ return sizeof(T_SAVE_FILE_DATA) + ap_len + ps_len;
++}
++
++static int sc_debug_info_record_from_user(const char *info, size_t count)
++{
++ UINT32 cnt = 0;
++ int spacelen;
++ int msg_len = 0;
++ struct tm tm;
++ time64_t time;
++ unsigned long used_space;
++ char buffer[DEBUG_INFO_MAX_TOTAL_LEN];
++ unsigned long flags;
++ UINT8 *tmp_write_addr = buffer;
++
++ if (g_init_flag == 0 || info == NULL)
++ {
++ printk("debug_info not init or sc_debug_info_record_from_user info is NULL\n");
++ return DEBUG_INFO_ERROR;
++ }
++
++ if(count > DEBUG_INFO_MAX_DATA_LEN + DEBUG_INFO_MAX_ID_LEN)
++ {
++ printk("debug_info data too long\n");
++ return DEBUG_INFO_ERROR;
++ }
++
++ time = ktime_get_real_seconds();
++ time64_to_tm(time, 0, &tm);
++ cnt = snprintf((char *)tmp_write_addr, DEBUG_INFO_MAX_DATE_LEN, "[%ld-%02d-%02d %d:%02d:%02d]", \
++ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
++ tmp_write_addr += cnt;
++ msg_len = cnt;
++
++ spin_lock_irqsave(&debug_info_lock, flags);
++ spacelen = g_ap_debug_buffer_end - g_ap_debug_buffer_write;
++ if (spacelen < msg_len + count)
++ {
++ g_ap_debug_write_cnt += spacelen;
++ memset(g_ap_debug_buffer_write, '\0', spacelen);
++ g_ap_debug_buffer_write = g_ap_debug_buffer_start;
++ }
++ memcpy(g_ap_debug_buffer_write, buffer, msg_len);
++ if (copy_from_user(g_ap_debug_buffer_write + msg_len, info, count))
++ return -EFAULT;
++ msg_len += count;
++ g_ap_debug_buffer_write += msg_len;
++ g_ap_debug_write_cnt += msg_len;
++ used_space = g_ap_debug_write_cnt - g_ap_debug_read_cnt;
++ spin_unlock_irqrestore(&debug_info_lock, flags);
++ if (used_space > DEBUG_INFO_READABLE_LEN)
++ {
++ if (debug_sem.count == 0)
++ {
++ up(&debug_sem);
++ }
++ }
++ return msg_len;
++}
++
++int sc_debug_info_vrecord(char *id, const char *format, va_list args)
++{
++ int spacelen;
++ int msg_len = 0;
++ int cnt = 0;
++ unsigned long used_space;
++ struct tm tm;
++ time64_t time;
++ char buffer[DEBUG_INFO_MAX_TOTAL_LEN];
++ unsigned long flags;
++ UINT8 *tmp_write_addr = buffer;
++
++ time = ktime_get_real_seconds();
++ time64_to_tm(time, 0, &tm);
++ cnt = snprintf((char *)tmp_write_addr, DEBUG_INFO_MAX_DATE_LEN, "[%ld-%02d-%02d %d:%02d:%02d]", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
++ tmp_write_addr += cnt;
++ msg_len = cnt;
++
++ cnt = snprintf((char *)tmp_write_addr, DEBUG_INFO_MAX_ID_LEN, "[%s]",id);
++ tmp_write_addr += cnt;
++ msg_len += cnt;
++ msg_len += vsnprintf((char *)tmp_write_addr, DEBUG_INFO_MAX_DATA_LEN, format, args);
++
++ spin_lock_irqsave(&debug_info_lock, flags);
++ spacelen = g_ap_debug_buffer_end - g_ap_debug_buffer_write;
++ if (spacelen < DEBUG_INFO_MAX_TOTAL_LEN)
++ {
++ g_ap_debug_write_cnt += spacelen;
++ memset(g_ap_debug_buffer_write, '\0', spacelen);
++ g_ap_debug_buffer_write = g_ap_debug_buffer_start;
++ }
++
++ memcpy(g_ap_debug_buffer_write, buffer, msg_len);
++ g_ap_debug_buffer_write += msg_len;
++ g_ap_debug_write_cnt += msg_len;
++ used_space = g_ap_debug_write_cnt - g_ap_debug_read_cnt;
++ spin_unlock_irqrestore(&debug_info_lock, flags);
++ if (used_space > DEBUG_INFO_READABLE_LEN)
++ {
++ if (debug_sem.count == 0)
++ {
++ up(&debug_sem);
++ }
++ }
++ return msg_len;
++}
++EXPORT_SYMBOL(sc_debug_info_vrecord);
++
++int sc_debug_info_record(char *id, const char *format, ...)
++{
++ va_list args;
++ int r;
++
++ if (g_init_flag == 0)
++ {
++ printk("debug_info not init.\n");
++ return DEBUG_INFO_ERROR;
++ }
++
++ va_start(args, format);
++ r = sc_debug_info_vrecord(id, format, args);
++ va_end(args);
++
++ return r;
++}
++EXPORT_SYMBOL(sc_debug_info_record);
++
++void early_debug_info_init(void)
++{
++ g_ap_debug_buffer_start = g_ap_debug_buffer;
++ g_ap_debug_buffer_write = g_ap_debug_buffer_start;
++ g_ap_debug_buffer_read = g_ap_debug_buffer_start;
++ g_ap_debug_buffer_end = g_ap_debug_buffer + DEBUG_INFO_AP_MEM_LEN;
++ g_ap_debug_read_cnt = 0;
++ g_ap_debug_write_cnt = 0;
++
++ g_init_flag = 1;
++ printk("cap early_debug_info_init success \n");
+ }
+
+ static int __init debug_info_init(void)
+ {
+- int ret = misc_register(&debug_info_device);
++ int ret;
++
++ ret = misc_register(&debug_info_device);
+ if (ret)
+ {
+- printk("debug_info_device init.\n");
++ printk("debug_info_init init.\n");
+ return DEBUG_INFO_ERROR;
+ }
+
+- void *mem;
+- mem = vmalloc(DEBUG_INFO_SHARE_MEM_LEN);
+- if (!mem)
+- {
+- printk("vmalloc failed.\n");
+- return DEBUG_INFO_ERROR;
+- }
+-
+- g_debug_info_buf = CreateRingBuffer((UINT8 *)mem, DEBUG_INFO_SHARE_MEM_LEN);
+- if (g_debug_info_buf == NULL)
+- {
+- printk("CreateRingBuffer failed.\n");
+- return DEBUG_INFO_ERROR;
+- }
+-#if 1
+- ret = rpmsgCreateChannel(
+- CORE_PS0,
+- DEBUG_INFO_CHANNEL,
+- DEBUG_INFO_MSG_CAP_SIZE);
+- if (ret != DEBUG_INFO_OK)
+- {
+- printk("rpmsgCreateChannel failed, ret = %d\n", ret);
+- return DEBUG_INFO_ERROR;
+- }
+-
+- ret = rpmsgRegCallBack(
+- CORE_PS0,
+- DEBUG_INFO_CHANNEL,
+- sc_debug_info_from_ap);
+- if (ret != DEBUG_INFO_OK)
+- {
+- printk("rpmsgRegCallBack failed,ret = %d\n", ret);
+- return DEBUG_INFO_ERROR;
+- }
+-#endif
++ g_ps_debug_write_cnt = (UINT32 *)ioremap(PS_DEBUG_INFO_LEN_ADDR_PA, PS_DEBUG_INFO_LEN_SIZE);
++ // printf("PS_DEBUG_INFO_LEN_ADDR_PA \n",)
++ g_ps_debug_full_cnt = (UINT32 *)((char *)g_ps_debug_write_cnt + 4);
++ g_ps_debug_buffer_start = (unsigned long)ioremap(PS_DEBUG_INFO_ADDR_PA, PS_DEBUG_INFO_SIZE);
++ g_ps_debug_buffer_read = g_ps_debug_buffer_start;
++ g_ps_debug_buffer_end = g_ps_debug_buffer_start + PS_DEBUG_INFO_SIZE;
++ g_ps_debug_read_cnt = 0;
++ g_ps_debug_read_full_cnt = 0;
+ sema_init(&debug_sem, 0);
+- /* 添加并启动定时器, 10ms */
+- mod_timer(&timer, jiffies + 1);
+-
+- g_init_flag = 1;
+-
++ proc_create_single("debug_info_cap", 0, NULL, ap_log_proc_show);
++ proc_create_single("debug_info_ap", 0, NULL, ps_log_proc_show);
++ mod_timer(&timer, jiffies + 1);
++ printk("cap debug_info_init success \n");
++ // g_init_flag = 1;
+ return 0;
+ }
+
+ static void __exit debug_info_exit(void)
+ {
+ misc_deregister(&debug_info_device);
+-
+ del_timer(&timer);
+ }
+
+-static int sc_debug_info_write(UINT32 flag, const UINT8 *buf, UINT32 len)
+-{
+- UINT32 writelen;
+- UINT32 used_space;
+- unsigned long flags;
+-
+- if (len == 0 || g_debug_info_buf == NULL)
+- {
+- printk("sc_debug_info_write:: (len == 0 || g_debug_info_buf == NULL).\n");
+- return DEBUG_INFO_ERROR;
+- }
+-
+- raw_spin_lock_irqsave(&debugWr_lock, flags);
+- writelen = WriteRingBuffer(g_debug_info_buf, buf, len, flag);
+- raw_spin_unlock_irqrestore(&debugWr_lock, flags);
+- used_space = GetRingBufferSize(g_debug_info_buf);
+- if (used_space > DEBUG_INFO_READABLE_LEN)
+- {
+- if (debug_sem.count == 0)
+- {
+- up(&debug_sem);
+- }
+- }
+-
+- return writelen;
+-}
+-
+-static int sc_debug_info_read_to_user(char *buf, unsigned short count)
+-{
+- unsigned int bufSize_used = 0;
+- unsigned int readLen = 0;
+- unsigned int bufLen = 0;
+- T_SAVE_FILE_DATA fileDataHead;
+-
+- if (g_init_flag == 0)
+- {
+- printk("debug_info not init.\n");
+- return DEBUG_INFO_ERROR;
+- }
+- if (count == 0 || buf == NULL || g_debug_info_buf == NULL)
+- {
+- printk("sc_debug_info_read_to_user:: (count == 0 || buf == NULL || g_debug_info_buf == NULL).\n");
+- return DEBUG_INFO_ERROR;
+- }
+-
+- bufSize_used = GetRingBufferSize(g_debug_info_buf);
+- if (bufSize_used == 0)
+- {
+- // printk("sc_debug_info_read_to_user:: ringBuf is empty.\n");
+- return 0;
+- }
+-
+- fileDataHead.head = 0x010a0a0a;
+- fileDataHead.time = 0;
+- fileDataHead.total_len = bufSize_used;
+-
+- copy_to_user(buf, &fileDataHead, sizeof(T_SAVE_FILE_DATA));
+-
+- readLen = ReadRingBuffer(g_debug_info_buf, (buf + sizeof(T_SAVE_FILE_DATA)), bufSize_used, ZCAT_MEM_TYPE_USER);
+- if (readLen == 0)
+- {
+- // printk("ReadRingBuffer failed.\n");
+- return 0;
+- }
+-
+- return (readLen + sizeof(T_SAVE_FILE_DATA));
+-}
+-
+-static int sc_debug_info_record_from_user(const char *info, unsigned short count)
+-{
+- unsigned int cnt = 0;
+- unsigned int my_jiffies = jiffies;
+-
+- if (g_init_flag == 0)
+- {
+- printk("debug_info not init.\n");
+- return DEBUG_INFO_ERROR;
+- }
+- if (info == NULL)
+- {
+- printk("sc_debug_info_record_from_user:: info is NULL.\n");
+- return DEBUG_INFO_ERROR;
+- }
+-
+- copy_to_user(info + 4, &my_jiffies, sizeof(my_jiffies));
+- cnt = sc_debug_info_write(ZCAT_MEM_TYPE_USER, (UINT8 *)info, count);
+-
+- return cnt;
+-}
+-
+ module_init(debug_info_init);
+ module_exit(debug_info_exit);
+-
+-MODULE_AUTHOR("jcw");
+ MODULE_DESCRIPTION("debug_info driver");
+ MODULE_LICENSE("GPL");
+
+-
+-int sc_debug_info_vrecord(unsigned int id, const char *format, va_list args)
+-{
+- int len;
+- UINT32 writelen;
+- // va_list args;
+- char str_buf[DEBUG_INFO_MAX_TOTAL_LEN] __attribute__((aligned(4)));
+- T_SHARED_MEM_DATA *shareMemData = (T_SHARED_MEM_DATA *)str_buf;
+-
+- if (g_init_flag == 0)
+- {
+- printk("debug_info not init.\n");
+- return DEBUG_INFO_ERROR;
+- }
+-
+- /* args是一个char*类型指针,指向format之后的第一个参数*/
+- // va_start(args, format);
+- len = vsnprintf(shareMemData->sub_data, DEBUG_INFO_MAX_DATA_LEN, format, args);
+- // va_end(args);
+- if (len < 0)
+- {
+- printk("vsnprintf format error.\n");
+- return DEBUG_INFO_ERROR;
+- }
+-
+- shareMemData->module_id = (UINT16)(id & 0xFFFF);
+- shareMemData->sub_len = len;
+- shareMemData->time = jiffies;
+-
+- writelen = sc_debug_info_write(ZCAT_MEM_TYPE_KERNEL, (UINT8 *)shareMemData, len + sizeof(T_SHARED_MEM_DATA));
+- return writelen;
+-}
+-EXPORT_SYMBOL(sc_debug_info_vrecord);
+-
+-int sc_debug_info_record(unsigned int id, const char *format, ...)
+-{
+- va_list args;
+- int r;
+-
+- va_start(args, format);
+- r = sc_debug_info_vrecord(id, format, args);
+- va_end(args);
+-
+-
+- return r;
+-}
+-EXPORT_SYMBOL(sc_debug_info_record);
+ #else
+-int sc_debug_info_record(unsigned int id, const char *format, ...)
++int sc_debug_info_record(char *id, const char *format, ...)
+ {
+- return 0;
++ return 0;
+ }
+ #endif /* _USE_ZXIC_DEBUG_INFO */
+
++
+diff --git a/upstream/linux-5.10/drivers/mmc/core/mmc_ramdump.c b/upstream/linux-5.10/drivers/mmc/core/mmc_ramdump.c
+index f72860e..be7309c 100755
+--- a/upstream/linux-5.10/drivers/mmc/core/mmc_ramdump.c
++++ b/upstream/linux-5.10/drivers/mmc/core/mmc_ramdump.c
+@@ -20,7 +20,7 @@
+ #define MMC1_REG_BASE 0x1211000
+ #define MATRIX_CRM_REG_BASE 0x1306000
+ #define CFG_EMMC_CLK_ENUM 400000
+-#define CFG_EMMC_CLK_WORK 26000000
++#define CFG_EMMC_CLK_WORK 50000000
+ #define CFG_EMMC_CLK_REF 50000000
+
+ #define ZXMCI_FIFO_DEPTH 128
+diff --git a/upstream/linux-5.10/drivers/net/zvnet/zvnet_dev.c b/upstream/linux-5.10/drivers/net/zvnet/zvnet_dev.c
+index 2a8fcc3..c7da7a4 100755
+--- a/upstream/linux-5.10/drivers/net/zvnet/zvnet_dev.c
++++ b/upstream/linux-5.10/drivers/net/zvnet/zvnet_dev.c
+@@ -8,7 +8,7 @@
+ #include "zvnet_dev.h"
+ #include "ram_config.h"
+ #include <net/netfilter/nf_conntrack.h>
+-
++#include <net/SI/fast_common.h>
+ /*******************************************************************************
+ * Macro definitions *
+ ******************************************************************************/
+@@ -72,10 +72,8 @@
+ module_param(g_wrap_num, int, 0644);
+ unsigned int g_wrap_timeout = 10;
+ module_param(g_wrap_timeout, int, 0644);
+-/*jb.qi add for debug network package on 20240806 start*/
+ unsigned int g_trace_limit = 0;
+ module_param(g_trace_limit, int, 0644);
+-/*jb.qi add for debug network package on 20240806 end*/
+ #endif
+
+ /*******************************************************************************
+@@ -85,7 +83,6 @@
+ extern void v7_dma_map_area(const void *, size_t, int);
+ extern void *get_ct_for_ap(struct sk_buff *skb);
+ extern void put_ct_for_ap(void *ct);
+-extern spinlock_t fast_fw_spinlock;
+ /*******************************************************************************
+ * Local function declarations *
+ ******************************************************************************/
+@@ -128,38 +125,41 @@
+ return NULL;
+ }
+
++/* Started by AICoder, pid:2fa080381bb2e3d14fbc0aa44091291a60d78e35 */
+ void check_skb_test(struct sk_buff *skb)
+ {
+- if(skb && vir_addr_ap){
+- struct sk_buff *tmp_skb;
+- if((skb->capHead && (virt_to_phys_ap(skb->head) == NULL))
+- || ((skb->capHead == NULL) && virt_to_phys_ap(skb->head))){
+- dump_stack();
+- msleep(1000);
+- panic("capHead err");
+- }
+- skb_queue_walk(&g_zvnet_skb_queue, tmp_skb) {
+- if(tmp_skb == skb){
+- dump_stack();
+- msleep(1000);
+- panic("dup free");
+- }
+- }
+- }
++ if (skb && vir_addr_ap) {
++ struct sk_buff *tmp_skb;
++ if ((skb->capHead && (virt_to_phys_ap(skb->head) == NULL))
++ || ((skb->capHead == NULL) && virt_to_phys_ap(skb->head))) {
++ dump_stack();
++ panic("capHead err");
++ }
++ skb_queue_walk(&g_zvnet_skb_queue, tmp_skb) {
++ if (tmp_skb == skb) {
++ dump_stack();
++ panic("dup free");
++ }
++ }
++ }
+ }
+-/*jb.qi add for debug network package on 20240806 start*/
++/* Ended by AICoder, pid:2fa080381bb2e3d14fbc0aa44091291a60d78e35 */
++
++/* Started by AICoder, pid:z5702yf8bad07ad1448a083e806dc31250b2418f */
+ void zvnet_dump_packet(unsigned char * data, int len, int limit_len)
+ {
+ int i = 0;
+-
+- for(i = 0; i < len && i < limit_len; i=i+16)
++ unsigned char *p = data;
++ for(i = 0; i < len && i < limit_len; i+=16)
+ {
+- printk("0x%04x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",i,
+- *(data+i),*(data+i+1),*(data+i+2),*(data+i+3),*(data+i+4),*(data+i+5),*(data+i+6),*(data+i+7),
+- *(data+i+8),*(data+i+9),*(data+i+10),*(data+i+11),*(data+i+12),*(data+i+13),*(data+i+14),*(data+i+15));
++ printk("0x%04x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",i,
++ p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],
++ p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]);
++ p += 16;
+ }
+ }
+-/*jb.qi add for debug network package on 20240806 end*/
++/* Ended by AICoder, pid:z5702yf8bad07ad1448a083e806dc31250b2418f */
++
+ int zvnet_get_index_by_netdev(struct net_device *net)
+ {
+ int i;
+@@ -304,13 +304,11 @@
+ /* make sure we initialize shinfo sequentially */
+ skb_reset_network_header(skb);
+ skb_set_kcov_handle(skb, kcov_common_handle());
+- /*jb.qi add for debug network package on 20240806 start*/
+ if(unlikely(g_trace_limit > 0)){
+- printk("-%s-dump_packet-start-%d\n", skb->dev->name, skb->len);
+- zvnet_dump_packet(skb->data, skb->len, g_trace_limit);
+- printk("-%s-dump_packet-end-\n", skb->dev->name);
+- }
+- /*jb.qi add for debug network package on 20240806 end*/
++ printk("-%s-dump_packet-start-%d\n", skb->dev->name, skb->len);
++ zvnet_dump_packet(skb->data, skb->len, g_trace_limit);
++ printk("-%s-dump_packet-end-\n", skb->dev->name);
++ }
+ return skb;
+ }
+
+@@ -321,33 +319,38 @@
+ return 0;
+ }
+
++/* Started by AICoder, pid:b001dtf2551fd53146790a57201be3321cf0a682 */
+ static void skb_debug_test(struct sk_buff *skb)
+ {
+ int i;
+- int vcount = skb->len/10;
+- int rcount = skb->len%10;
++ int vcount = skb->len / 10;
++ int rcount = skb->len % 10;
+ char tmp[64] = {0};
+ char strbuf[64] = {0};
++ const unsigned char *data = skb->data;
+
+ zv_info("\n");
+- for(i=0; i<vcount; i++) {
+- zv_info("%d---0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n",i,skb->data[0+10*i],skb->data[1+10*i],skb->data[2+10*i],
+- skb->data[3+10*i],skb->data[4+10*i],skb->data[5+10*i],skb->data[6+10*i],skb->data[7+10*i],skb->data[8+10*i],skb->data[9+10*i]);
++ for (i = 0; i < vcount; i++) {
++ zv_info("%d---%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n", i,
++ data[0 + 10 * i], data[1 + 10 * i], data[2 + 10 * i], data[3 + 10 * i],
++ data[4 + 10 * i], data[5 + 10 * i], data[6 + 10 * i], data[7 + 10 * i],
++ data[8 + 10 * i], data[9 + 10 * i]);
+ }
+- if(vcount > 0) {
+- memset(tmp,0,sizeof(tmp));
+- memset(strbuf,0,sizeof(strbuf));
+- sprintf(strbuf,"%d---",vcount);
++ if (vcount > 0) {
++ memset(tmp, 0, sizeof(tmp));
++ sprintf(strbuf, "%d---", vcount);
++ char *p = strbuf + strlen(strbuf);
+
+- for(i=0; i<rcount; i++)
+- {
+- sprintf(tmp,"0x%x,",skb->data[10*vcount + i]);
+- strcat(strbuf,tmp);
++ for (i = 0; i < rcount; i++) {
++ sprintf(p, "%02x,", data[10 * vcount + i]);
++ p += strlen(p);
+ }
+- zv_info("%s ",strbuf);
++ *(p - 1) = '\0'; // ÒÆ³ý×îºóÒ»¸ö¶ººÅ
++ zv_info("%s ", strbuf);
+ }
+ zv_info("\n");
+ }
++/* Ended by AICoder, pid:b001dtf2551fd53146790a57201be3321cf0a682 */
+
+ static int zvnet_open(struct net_device *net)
+ {
+@@ -473,8 +476,8 @@
+ return NET_XMIT_SUCCESS;
+ }
+
+- if(unlikely(skb_headroom(skb) < NET_SKB_PAD || skb->next//|| skb->capHead
+- || skb->fclone || skb->cloned || (skb_shinfo(skb)->nr_frags) || skb->sk || (skb->indev == NULL)
++ if(unlikely(skb->next//|| skb->capHead || skb_headroom(skb) < NET_SKB_PAD
++ || skb->fclone || skb->cloned || (skb_shinfo(skb)->nr_frags) || skb->sk || (skb->indev == NULL)
+ || (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) || (skb_has_frag_list(skb)))){
+ int ret_len = skb->len;
+
+@@ -632,6 +635,7 @@
+ .ndo_get_stats = zvnet_get_stats,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
++ .ndo_set_mac_address = eth_mac_addr,
+ };
+
+ static void v2xnet_init_netdev(struct net_device *net)
+@@ -802,30 +806,32 @@
+ {
+ struct sk_buff *skb;
+ #if 0
+- char skb_data[ZVNET_TMP_BUFF_LEN];
+- int ret_len = 0;
++/* Started by AICoder, pid:sd1cfsbc2eu87c41445f09652039f525fa147687 */
++int ret_len = 0;
++struct sk_buff *skb;
+
+- if(NULL == chninfo || NULL == dev) {
+- zv_err("zvnet_channel_read null.\n");
+- return NULL;
+- }
++ret_len = zvnet_channel_read(chninfo, NULL, 0); // »ñÈ¡ÐèÒª¶ÁÈ¡µÄÊý¾Ý³¤¶È
++if(ret_len <= 0) {
++ zv_err("zvnet_channel_read fail.\n");
++ return NULL;
++}
+
+- ret_len = zvnet_channel_read(chninfo, (void *)skb_data, sizeof(skb_data));
++skb = dev_alloc_skb(ret_len + ZVNET_SKB_PAD);
++if (unlikely(!skb)) {
++ zv_err("netdev_alloc_skb fail,len %d",ret_len);
++ return NULL;
++}
+
+- if(ret_len <= 0) {
+- zv_err("zvnet_channel_read fail.\n");
+- return NULL;
+- }
++ret_len = zvnet_channel_read(chninfo, skb->data, ret_len); // ¶ÁÈ¡Êý¾Ýµ½skb->data
++if(ret_len <= 0) {
++ kfree_skb(skb); // Èç¹û¶Áȡʧ°Ü£¬ÊÍ·ÅÒÑ·ÖÅäµÄskb
++ zv_err("zvnet_channel_read fail.\n");
++ return NULL;
++}
+
+- skb = dev_alloc_skb(ret_len + ZVNET_SKB_PAD);
+- if (unlikely(!skb)) {
+- zv_err("netdev_alloc_skb fail,len %d",ret_len);
+- return NULL;
+- }
+-
+- skb_put(skb,ret_len);
+- skb_reserve(skb, ZVNET_SKB_PAD);
+- memcpy(skb->data, &skb_data[0], ret_len);
++skb_put(skb,ret_len);
++skb_reserve(skb, ZVNET_SKB_PAD);
++/* Ended by AICoder, pid:sd1cfsbc2eu87c41445f09652039f525fa147687 */
+ #else
+ struct T_zvnet_rpmsg buff = {0};
+ int ret_len = 0;
+@@ -1099,6 +1105,9 @@
+ .flag = 0};
+ int ret_len = 0;
+ struct nf_conn *ct;
++ fast_entry_t *entry;
++ struct net_device *in;
++ struct net_device *out;
+
+ while(1) {
+ struct T_zvnet_rpmsg_ctstat buff = {0};
+@@ -1115,33 +1124,104 @@
+ panic("err, ret:%d!!!!!!", ret_len);
+ }
+ ct = (struct nf_conn *)buff.cap_nfct;
+-
+ WARN_ON(atomic_read(&ct->ct_general.use) == 0);
+ if(buff.flag){
++ if(!(buff.pkt[0].pkt || buff.pkt[0].len || buff.pkt[1].pkt || buff.pkt[1].len))
++ continue;
+ BUG_ON(buff.in <= 0 || buff.out <= 0);
++ in = zvnet_dev[buff.in-1].net;
++ out = zvnet_dev[buff.out-1].net;
+ if(buff.pkt[0].pkt && buff.pkt[0].len){
+ zv_info("nf_update %x %s %s %d %d", buff.cap_nfct, ct->indev[0]->name, ct->outdev[0]->name, buff.in, buff.out);
+- zvnet_dev[buff.in-1].net->stats.rx_packets += buff.pkt[0].pkt;
+- zvnet_dev[buff.in-1].net->stats.rx_bytes += buff.pkt[0].len;
+- zvnet_dev[buff.out-1].net->stats.tx_packets += buff.pkt[0].pkt;
+- zvnet_dev[buff.out-1].net->stats.tx_bytes += buff.pkt[0].len;
++ in->stats.rx_packets += buff.pkt[0].pkt;
++ in->stats.rx_bytes += buff.pkt[0].len;
++ out->stats.tx_packets += buff.pkt[0].pkt;
++ out->stats.tx_bytes += buff.pkt[0].len;
+ }
+ if(buff.pkt[1].pkt && buff.pkt[1].len){
+ zv_info("nf_update %x %s %s %d %d", buff.cap_nfct, ct->indev[1]->name, ct->outdev[1]->name, buff.out, buff.in);
+- zvnet_dev[buff.out-1].net->stats.rx_packets += buff.pkt[1].pkt;
+- zvnet_dev[buff.out-1].net->stats.rx_bytes += buff.pkt[1].len;
+- zvnet_dev[buff.in-1].net->stats.tx_packets += buff.pkt[1].pkt;
+- zvnet_dev[buff.in-1].net->stats.tx_bytes += buff.pkt[1].len;
++ out->stats.rx_packets += buff.pkt[1].pkt;
++ out->stats.rx_bytes += buff.pkt[1].len;
++ in->stats.tx_packets += buff.pkt[1].pkt;
++ in->stats.tx_bytes += buff.pkt[1].len;
+ }
+ spin_lock_bh(&fast_fw_spinlock);
++ /*¸üÐÂÁ´½Ó³¬Ê±*/
++ if (IPPROTO_TCP == nf_ct_protonum(ct))
++ {
++ ct->timeout = jiffies + tcp_timeouts[ct->proto.tcp.state];
++ }else if (IPPROTO_UDP == nf_ct_protonum(ct)){
++ /*udp*/
++ if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)){
++ ct->timeout = jiffies + fast_udp_timeout_stream;
++ }else{
++ ct->timeout = jiffies + fast_udp_timeout;
++ }
++ }
++ entry = (fast_entry_t *)ct->fast_entry;
++ if(entry){
++ WARN_ON(entry->ct != ct);
++ mod_timer(&entry->timeout, ct->timeout);
++ }
+ ct->packet_info[IP_CT_DIR_ORIGINAL].bytes += buff.pkt[IP_CT_DIR_ORIGINAL].len;
+ ct->packet_info[IP_CT_DIR_ORIGINAL].packets += buff.pkt[IP_CT_DIR_ORIGINAL].pkt;
+ ct->packet_info[IP_CT_DIR_REPLY].bytes += buff.pkt[IP_CT_DIR_REPLY].len;
+ ct->packet_info[IP_CT_DIR_REPLY].packets += buff.pkt[IP_CT_DIR_REPLY].pkt;
++ if(ct->indev[0] && is_vlan_dev(ct->indev[0])){
++ struct net_device *tmp = vlan_dev_real_dev(ct->indev[0]);
++ struct vlan_pcpu_stats *stats = this_cpu_ptr(vlan_dev_priv(ct->indev[0])->vlan_pcpu_stats);
++
++ if(tmp == in){
++/* Started by AICoder, pid:tbef0151bf4135d1479d0a5d108c870bc756e858 */
++u64_stats_update_begin(&stats->syncp);
++stats->rx_packets += buff.pkt[0].pkt;
++stats->rx_bytes += buff.pkt[0].len;
++stats->tx_packets += buff.pkt[1].pkt;
++stats->tx_bytes += buff.pkt[1].len;
++u64_stats_update_end(&stats->syncp);
++/* Ended by AICoder, pid:tbef0151bf4135d1479d0a5d108c870bc756e858 */
++ }else if(tmp == out){
++/* Started by AICoder, pid:y34f7id6bcs049f144f10bb8a05c9703b196635b */
++u64_stats_update_begin(&stats->syncp);
++stats->tx_packets += buff.pkt[0].pkt;
++stats->tx_bytes += buff.pkt[0].len;
++stats->rx_packets += buff.pkt[1].pkt;
++stats->rx_bytes += buff.pkt[1].len;
++u64_stats_update_end(&stats->syncp);
++/* Ended by AICoder, pid:y34f7id6bcs049f144f10bb8a05c9703b196635b */
++ }else
++ zv_err("nf_update0 %s->%s!=%s-%s", in->name, out->name, tmp->name, ct->indev[0]->name);
++ }
++ if(ct->indev[1] && is_vlan_dev(ct->indev[1])){
++ struct net_device *tmp = vlan_dev_real_dev(ct->indev[1]);
++ struct vlan_pcpu_stats *stats = this_cpu_ptr(vlan_dev_priv(ct->indev[1])->vlan_pcpu_stats);
++
++ if(tmp == in){
++/* Started by AICoder, pid:8bef0t51bfu135d1479d0a5d108c870bc756e858 */
++u64_stats_update_begin(&stats->syncp);
++stats->rx_packets += buff.pkt[0].pkt;
++stats->rx_bytes += buff.pkt[0].len;
++stats->tx_packets += buff.pkt[1].pkt;
++stats->tx_bytes += buff.pkt[1].len;
++u64_stats_update_end(&stats->syncp);
++/* Ended by AICoder, pid:8bef0t51bfu135d1479d0a5d108c870bc756e858 */
++ }else if(tmp == out){
++/* Started by AICoder, pid:934f7zd6bcl049f144f10bb8a05c9703b196635b */
++u64_stats_update_begin(&stats->syncp);
++stats->tx_packets += buff.pkt[0].pkt;
++stats->tx_bytes += buff.pkt[0].len;
++stats->rx_packets += buff.pkt[1].pkt;
++stats->rx_bytes += buff.pkt[1].len;
++u64_stats_update_end(&stats->syncp);
++/* Ended by AICoder, pid:934f7zd6bcl049f144f10bb8a05c9703b196635b */
++ }else
++ zv_err("nf_update1 %s->%s!=%s-%s", in->name, out->name, tmp->name, ct->indev[1]->name);
++ }
+ spin_unlock_bh(&fast_fw_spinlock);
+ zv_info("nf_update %x %d %d %d %d", buff.cap_nfct, buff.pkt[0].pkt, buff.pkt[0].len, buff.pkt[1].pkt, buff.pkt[1].len);
+ }else{
+ zv_info("nf_put %x", buff.cap_nfct);
++ WRITE_ONCE(ct->timeout, nfct_time_stamp);
+ nf_conntrack_put(buff.cap_nfct);
+ }
+ }
+@@ -1179,11 +1259,11 @@
+ return err;
+ }
+
+- net->needed_headroom += ZVNET_SKB_PAD;//NET_SKB_PAD;
++ //net->needed_headroom += ZVNET_SKB_PAD;//NET_SKB_PAD;
+ sprintf(net->name, "%s%d", ZVNET_IFNAME_PREFIX, i);
+ dev = v2xnet_dev_init(net, zvnetdev);
+ v2xnet_init_netdev(net);
+- if(0 == i){
++ if(0 == i || i > 8){
+ net->flags = (net->flags & (~IFF_NOARP));
+ }
+ err = register_netdev(net);
+diff --git a/upstream/linux-5.10/drivers/net/zvnet/zvnet_dev.h b/upstream/linux-5.10/drivers/net/zvnet/zvnet_dev.h
+index d1feaa5..7c46dd3 100755
+--- a/upstream/linux-5.10/drivers/net/zvnet/zvnet_dev.h
++++ b/upstream/linux-5.10/drivers/net/zvnet/zvnet_dev.h
+@@ -27,7 +27,7 @@
+ __func__ , ## arg)
+
+ //zvnetÉ豸×î´óÊý
+-#define DDR_ZVNET_DEV_MAX 10
++#define DDR_ZVNET_DEV_MAX 16
+ #define ZVNET_IFNAME_PREFIX "zvnet"
+
+ #define ICP_CHN_ZVNET1 20 //ICP_CHANNEL_WAN1
+diff --git a/upstream/linux-5.10/drivers/rtc/class.c b/upstream/linux-5.10/drivers/rtc/class.c
+index 625effe..87310ce 100755
+--- a/upstream/linux-5.10/drivers/rtc/class.c
++++ b/upstream/linux-5.10/drivers/rtc/class.c
+@@ -19,6 +19,7 @@
+ #include <linux/workqueue.h>
+
+ #include "rtc-core.h"
++#include "pub_debug_info.h"
+
+ static DEFINE_IDA(rtc_ida);
+ struct class *rtc_class;
+@@ -80,7 +81,7 @@
+ #endif
+
+ err = do_settimeofday64(&tv64);
+-
++ sc_debug_info_record("hctosys", "time synchronization successful!\r\n");
+ dev_info(rtc->dev.parent, "setting system clock to %ptR UTC (%lld)\n",
+ &tm, (long long)tv64.tv_sec);
+
+diff --git a/upstream/linux-5.10/drivers/soc/sc/pcu/pcu-zx297520v3.c b/upstream/linux-5.10/drivers/soc/sc/pcu/pcu-zx297520v3.c
+index 66c8cf3..f9b23d7 100755
+--- a/upstream/linux-5.10/drivers/soc/sc/pcu/pcu-zx297520v3.c
++++ b/upstream/linux-5.10/drivers/soc/sc/pcu/pcu-zx297520v3.c
+@@ -37,6 +37,7 @@
+ #include <linux/soc/sc/rpmsg.h>
+ #include <dt-bindings/soc/zx297520v3-irq.h>
+ #include <uapi/linux/sc_bsp/bsp_api.h>
++#include <pub_debug_info.h>
+
+ #include "pcu-common.h"
+
+@@ -705,6 +706,7 @@
+ if(index_found != 0xff)
+ {
+ pm_ram_log(" wake: %d [%s]\n", zx297520v3_pcu_int_info[index_found].gic_index, zx297520v3_pcu_int_info[index_found].int_name);
++ sc_debug_info_record(MODULE_ID_CAP_PM, " wake: %d [%s]\n", zx297520v3_pcu_int_info[index_found].gic_index, zx297520v3_pcu_int_info[index_found].int_name);
+
+ if(zx297520v3_pcu_int_info[index_found].gic_index ==ICP_PS2AP_INT) {
+ show_icp_state(CORE_PS0);
+diff --git a/upstream/linux-5.10/drivers/soc/sc/plat/plat-zx297520v3.c b/upstream/linux-5.10/drivers/soc/sc/plat/plat-zx297520v3.c
+index b2da8d9..2cf9b67 100755
+--- a/upstream/linux-5.10/drivers/soc/sc/plat/plat-zx297520v3.c
++++ b/upstream/linux-5.10/drivers/soc/sc/plat/plat-zx297520v3.c
+@@ -80,6 +80,8 @@
+ #define ZX_SPINLOCK_TEST 0
+ #define ZX_PM_QOS_TEST 1
+
++#define GPIO_HIGH 1
++#define GPIO_LOW 0
+
+ /*
+ *
+@@ -1898,6 +1900,10 @@
+ static int zx_restart(struct notifier_block *this,
+ unsigned long mode, void *cmd)
+ {
++ /*reset spinand cs*/
++ soft_spin_lock_nand_psm(NAND_SFLOCK);
++ gpio_set_value(86,GPIO_HIGH);
++
+ if (reboot_rst) {
+ reset_control_assert(reboot_rst);
+ }
+diff --git a/upstream/linux-5.10/drivers/soc/sc/power/zx29-cpufreq.c b/upstream/linux-5.10/drivers/soc/sc/power/zx29-cpufreq.c
+index 7eacfd7..1def959 100755
+--- a/upstream/linux-5.10/drivers/soc/sc/power/zx29-cpufreq.c
++++ b/upstream/linux-5.10/drivers/soc/sc/power/zx29-cpufreq.c
+@@ -219,9 +219,11 @@
+ return 0;
+
+ #ifdef SET_AXI_BY_HW
+- tmp = (pm_read_reg(PS_MATRIX_AXI_SEL)&(~0x7))|axi_freq;
+- pm_write_reg(PS_MATRIX_AXI_SEL,tmp);
+- pm_printk("[CPUFREQ] current_axi_freq(%d) request_axi_freq(%d) after_request_axi_freq(%d) after_request_vol(%d)\n",(u32)current_axi_freq,(u32)axi_freq,get_cur_axi(),get_cur_vol());
++/* Started by AICoder, pid:z8ed4zb53200a29148230ac670df2e16d7344ba7 */
++ tmp = (pm_read_reg(AP_MATRIX_AXI_SEL)&(~0x7))|axi_freq;
++ pm_write_reg(AP_MATRIX_AXI_SEL,tmp);
++ pm_printk("[CPUFREQ] current_axi_freq(%d) request_axi_freq(%d) after_request_axi_freq(%d) after_request_vol(%d)\n",(u32)current_axi_freq,(u32)axi_freq, (pm_read_reg(AP_MATRIX_AXI_SEL)&(0x7)),get_cur_vol());
++/* Ended by AICoder, pid:z8ed4zb53200a29148230ac670df2e16d7344ba7 */
+ #else
+ set_target_axi_sw(axi_freq);
+
+@@ -295,13 +297,9 @@
+
+ if(cpufreq_driver_inited==0)
+ return -EPERM;
+-
+- if(axifreq >= 600*1000*1000)
+- return AXI_FREQ_156M;
+- else
+- return AXI_FREQ_78M;
+-
+- return request_axi_freq(axi_freq);
++/* Started by AICoder, pid:keaa857ea2211111463f0b6cf00c182e9b179920 */
++ return request_axi_freq(axifreq);
++/* Ended by AICoder, pid:keaa857ea2211111463f0b6cf00c182e9b179920 */
+ }
+
+ #endif
+diff --git a/upstream/linux-5.10/drivers/soc/sc/rpmsg/zx29_icp.c b/upstream/linux-5.10/drivers/soc/sc/rpmsg/zx29_icp.c
+index aae42a2..3c5ba58 100755
+--- a/upstream/linux-5.10/drivers/soc/sc/rpmsg/zx29_icp.c
++++ b/upstream/linux-5.10/drivers/soc/sc/rpmsg/zx29_icp.c
+@@ -15,6 +15,7 @@
+ #include <linux/pm_runtime.h>
+ #include <linux/soc/sc/common.h>
+ #include <linux/soc/sc/spinlock.h>
++#include <pub_debug_info.h>
+
+ #include "icp_dev.h"
+ #include "zx29_icp.h"
+@@ -334,6 +335,7 @@
+
+ icp_get_int_info(actorID, &hw, &lw);
+ pr_info("[SLP] icpwake: 0x%x 0x%x\n", hw, lw);
++ sc_debug_info_record(MODULE_ID_CAP_PM, " icpwake: 0x%x 0x%x\n", hw, lw);
+
+ for (i=0; i<32; i++)
+ if (lw&BIT(i))
+diff --git a/upstream/linux-5.10/drivers/soc/sc/spinlock/spinlock-zx297520v3.c b/upstream/linux-5.10/drivers/soc/sc/spinlock/spinlock-zx297520v3.c
+index 7843e46..9e017da 100755
+--- a/upstream/linux-5.10/drivers/soc/sc/spinlock/spinlock-zx297520v3.c
++++ b/upstream/linux-5.10/drivers/soc/sc/spinlock/spinlock-zx297520v3.c
+@@ -300,6 +300,34 @@
+
+ }
+
++void soft_spin_lock_nand_psm(emsf_lock_id sfid)
++{
++ unsigned long lock_count = 0;
++softlock_loop:
++ while(softlock_desc[sfid]->owner != SELF_CORE_ID && softlock_desc[sfid]->used)
++ {
++ lock_count++;
++ udelay(1);
++ if(lock_count >= 100000)
++ {
++ return;
++ }
++ }
++
++ _hw_spin_lock(SOFTLOCK_HWLOCK);
++ if(softlock_desc[sfid]->owner != SELF_CORE_ID && softlock_desc[sfid]->used)
++ {
++ _hw_spin_unlock(SOFTLOCK_HWLOCK);
++ goto softlock_loop;
++ }
++ softlock_desc[sfid]->used ++;
++ softlock_desc[sfid]->owner = SELF_CORE_ID;
++ _hw_spin_unlock(SOFTLOCK_HWLOCK);
++ //zspinlock_debug("cpu %d releases %d software lock!/n",SELF_CORE_ID,sfid);
++
++}
++
++
+ /*******************************************************************************
+ * Function: soft_spin_unlock_psm
+ * Description:Óësoft_spin_lock_psm¶ÔÓ¦µÄÊÍ·ÅÈí¼þËø½Ó¿Ú¡£
+@@ -503,6 +531,7 @@
+ void soft_spin_lock(emsf_lock_id sfid){}
+ void soft_spin_unlock(emsf_lock_id sfid){}
+ void soft_spin_lock_psm(emsf_lock_id sfid){}
++void soft_spin_lock_nand_psm(emsf_lock_id sfid){}
+ void soft_spin_unlock_psm(emsf_lock_id sfid){}
+ void hw_spin_lock(emhw_lock_id hwid){}
+ void hw_spin_unlock(emhw_lock_id hwid){}
+diff --git a/upstream/linux-5.10/drivers/spi/spi-zx29.c b/upstream/linux-5.10/drivers/spi/spi-zx29.c
+index fd49fd6..57600dc 100755
+--- a/upstream/linux-5.10/drivers/spi/spi-zx29.c
++++ b/upstream/linux-5.10/drivers/spi/spi-zx29.c
+@@ -2341,7 +2341,9 @@
+ .iface = SPI_INTERFACE_MOTOROLA_SPI,
+ .hierarchy = SPI_MASTER,
+ .slave_tx_disable = DO_NOT_DRIVE_TX,
++ /* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck start */
+ .rx_lev_trig = SPI_RX_8_OR_MORE_ELEM,
++ /* yu.dong@20240521 [T106BUG-616] SPI set to slave mode for read will get stuck end */
+ .tx_lev_trig = SPI_TX_4_OR_MORE_EMPTY_LOC,
+ // .ctrl_len = SSP_BITS_8,
+ // .wait_state = SSP_MWIRE_WAIT_ZERO,
+diff --git a/upstream/linux-5.10/drivers/staging/Kconfig b/upstream/linux-5.10/drivers/staging/Kconfig
+index 443587b..aacc8d0 100755
+--- a/upstream/linux-5.10/drivers/staging/Kconfig
++++ b/upstream/linux-5.10/drivers/staging/Kconfig
+@@ -118,5 +118,7 @@
+
+ source "drivers/staging/hikey9xx/Kconfig"
+
++source "drivers/staging/voicedrv/Kconfig"
++
+ source "drivers/staging/voicebufferdrv/Kconfig"
+ endif # STAGING
+diff --git a/upstream/linux-5.10/drivers/staging/Makefile b/upstream/linux-5.10/drivers/staging/Makefile
+index 0cb5246..276dea6 100755
+--- a/upstream/linux-5.10/drivers/staging/Makefile
++++ b/upstream/linux-5.10/drivers/staging/Makefile
+@@ -49,4 +49,5 @@
+ obj-$(CONFIG_QLGE) += qlge/
+ obj-$(CONFIG_WFX) += wfx/
+ obj-y += hikey9xx/
++obj-$(CONFIG_VOICE_DRV) += voicedrv/
+ obj-$(CONFIG_VOICE_BUFFER_DRV) += voicebufferdrv/
+diff --git a/upstream/linux-5.10/drivers/staging/voicebufferdrv/voice_buffer_dev_multicore.c b/upstream/linux-5.10/drivers/staging/voicebufferdrv/voice_buffer_dev_multicore.c
+index 9c7d0c3..3beb425 100755
+--- a/upstream/linux-5.10/drivers/staging/voicebufferdrv/voice_buffer_dev_multicore.c
++++ b/upstream/linux-5.10/drivers/staging/voicebufferdrv/voice_buffer_dev_multicore.c
+Binary files differ
+diff --git a/upstream/linux-5.10/drivers/staging/voicedrv/Kconfig b/upstream/linux-5.10/drivers/staging/voicedrv/Kconfig
+new file mode 100755
+index 0000000..426928d
+--- /dev/null
++++ b/upstream/linux-5.10/drivers/staging/voicedrv/Kconfig
+@@ -0,0 +1,11 @@
++#
++# voice driver for voice in userspace of ZX297520
++#
++
++comment "ZX297520 voice driver"
++
++config VOICE_DRV
++ bool "Voice Drv"
++ default n
++ help
++ Select this to make sure the build voice driver
+diff --git a/upstream/linux-5.10/drivers/staging/voicedrv/Makefile b/upstream/linux-5.10/drivers/staging/voicedrv/Makefile
+new file mode 100755
+index 0000000..fbad610
+--- /dev/null
++++ b/upstream/linux-5.10/drivers/staging/voicedrv/Makefile
+@@ -0,0 +1,10 @@
++#
++# voice driver.
++#
++
++
++ccflags-y += -Idrivers/staging/voicedrv/include
++
++
++obj-$(CONFIG_VOICE_DRV) += voice_drv.o
++voice_drv-$(CONFIG_VOICE_DRV) := voice_cap.o
+diff --git a/upstream/linux-5.10/drivers/staging/voicedrv/include/voice.h b/upstream/linux-5.10/drivers/staging/voicedrv/include/voice.h
+new file mode 100755
+index 0000000..2566eb1
+--- /dev/null
++++ b/upstream/linux-5.10/drivers/staging/voicedrv/include/voice.h
+@@ -0,0 +1,17 @@
++/*
++ * Copyright (C) 2019 ZTE, China
++ *
++ * This is the header file for the voice driver.
++ *
++ */
++
++#ifndef __LINUX_VOICE_H
++#define __LINUX_VOICE_H
++
++
++
++
++
++
++
++#endif
+diff --git a/upstream/linux-5.10/drivers/staging/voicedrv/voice_cap.c b/upstream/linux-5.10/drivers/staging/voicedrv/voice_cap.c
+new file mode 100755
+index 0000000..3da1ad3
+--- /dev/null
++++ b/upstream/linux-5.10/drivers/staging/voicedrv/voice_cap.c
+@@ -0,0 +1,207 @@
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <asm/uaccess.h>
++#include <linux/slab.h>
++
++#include <linux/volte_drv.h>
++
++
++#include "include/voice.h"
++
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("xxq");
++
++static int s_voiceInfMode = 0;
++static DEFINE_MUTEX(infmode_lock);
++
++
++struct voice_dev *voicedev = NULL;
++static const char voice_shortname[] = "voice_device";
++
++
++
++
++static int voice_open(struct inode *ip, struct file *fp);
++static int voice_release(struct inode *ip, struct file *fp);
++static long voice_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
++
++
++
++
++
++
++static int voice_SetVoiceInfMode(int mode)
++{
++ int ret = 0;
++ mutex_lock(&infmode_lock);
++ s_voiceInfMode = mode;
++ mutex_unlock(&infmode_lock);
++ printk(KERN_INFO "%s:mode = %d\n",__func__,mode);
++
++ return ret;
++}
++
++static int voice_GetVoiceInfMode(void)
++{
++ int mode;
++ mutex_lock(&infmode_lock);
++ mode = s_voiceInfMode;
++ mutex_unlock(&infmode_lock);
++ printk(KERN_INFO "%s:mode = %d\n",__func__,s_voiceInfMode);
++ return mode;
++}
++
++
++
++
++/* file operations for volte device /dev/volte_device */
++static const struct file_operations voice_fops = {
++ .owner = THIS_MODULE,
++ //.read = voice_read,
++ //.write = voice_write,
++ .unlocked_ioctl = voice_ioctl,
++ .open = voice_open,
++ .release = voice_release,
++};
++
++static struct miscdevice voice_device = {
++ .minor = MISC_DYNAMIC_MINOR,
++ .name = voice_shortname,
++ .fops = &voice_fops,
++};
++
++
++#if 0
++static ssize_t voice_read(struct file *fp, char __user *buf, size_t count, loff_t *pos)
++{
++ struct adbproxy_dev *dev = fp->private_data;
++ struct usbproxy_request *req;
++ int r = count, xfer;
++ int ret;
++ return count;
++}
++
++static ssize_t voice_write(struct file *fp, const char __user *buf, size_t count, loff_t *pos)
++{
++ int ret;
++
++
++ return count;
++}
++#endif
++
++
++static long voice_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
++{
++ int ret = 0;
++ void __user *argp = (void __user *) arg;
++#ifndef CONFIG_RECOVERY_SYSTEM
++
++ switch (cmd) {
++
++
++ case VOICE_IOCTL_GET_INF_MODE: {
++
++ int mode;
++ mode = voice_GetVoiceInfMode();
++
++ pr_info("voice_ioctl GET_VBUF,mode=%d!\n",mode);
++
++ if (copy_to_user(argp, &mode, sizeof(mode))) {
++ pr_err("voice_ioctl GetVoiceInfMode copy_to_user err!\n");
++ return -EFAULT;
++ }
++
++ break;
++ }
++
++ case VOICE_IOCTL_SET_INF_MODE: {
++ int para;
++
++ if (copy_from_user(¶, argp, sizeof(para))) {
++ print_audio("voice_ioctl SetVoiceInfMode copy_to_user err!\n");
++ return -EFAULT;
++ }
++ ret = voice_SetVoiceInfMode(para);
++ if (ret < 0)
++ print_audio("%s SetVoiceInfMode ret=%d\n", __func__, ret);
++
++ break;
++ }
++
++
++ default: {
++ pr_info("voice_ioctl invalid cmd!\n");
++ break;
++ }
++ }
++#endif
++
++ return ret;
++}
++
++
++
++static int voice_open(struct inode *ip, struct file *fp)
++{
++// pr_info("volte_open\n");
++
++#ifndef CONFIG_RECOVERY_SYSTEM
++ if (voicedev == NULL) {
++ voicedev = kzalloc(sizeof(*voicedev), GFP_KERNEL);
++ if (!voicedev) {
++ pr_info("voice_init malloc error\n");
++ return -ENOMEM;
++ }
++
++
++ }
++
++#endif
++
++ return 0;
++}
++
++static int voice_release(struct inode *ip, struct file *fp)
++{
++// pr_info("volte_release\n");
++#ifndef CONFIG_RECOVERY_SYSTEM
++ if (voicedev) {
++ kfree(voicedev);
++ voicedev = NULL;
++ print_audio("release voicedev!\n");
++
++ }
++#endif
++
++ return 0;
++}
++
++
++static int __init voice_init(void)
++{
++ int ret;
++// pr_info("volte_init\n");
++
++ ret = misc_register(&voice_device);
++ if (ret) {
++ printk(KERN_ERR "voice driver failed to initialize\n");
++ return -EFAULT;
++ }
++// pr_info("voice_init volte_device nodename=%s\n",volte_device.nodename);
++
++ return 0;
++}
++
++
++static void __exit voice_exit(void)
++{
++ misc_deregister(&voice_device);
++}
++
++module_init(voice_init);
++module_exit(voice_exit);
+diff --git a/upstream/linux-5.10/drivers/tty/tty_io.c b/upstream/linux-5.10/drivers/tty/tty_io.c
+index 669aef7..8591d06 100755
+--- a/upstream/linux-5.10/drivers/tty/tty_io.c
++++ b/upstream/linux-5.10/drivers/tty/tty_io.c
+@@ -771,6 +771,12 @@
+ if (tty->stopped)
+ return;
+ tty->stopped = 1;
++
++ //l.yang add log for bug T106-134 start
++ if(tty->index == 1){
++ printk("__stop_tty got stop cmd\n");
++ }
++ //l.yang add log for bug T106-134 end
+ if (tty->ops->stop)
+ tty->ops->stop(tty);
+ }
+diff --git a/upstream/linux-5.10/include/linux/soc/sc/spinlock.h b/upstream/linux-5.10/include/linux/soc/sc/spinlock.h
+index eb5e7b7..17faf8b 100755
+--- a/upstream/linux-5.10/include/linux/soc/sc/spinlock.h
++++ b/upstream/linux-5.10/include/linux/soc/sc/spinlock.h
+@@ -103,7 +103,7 @@
+ void reg_spin_unlock(void);
+ void soft_spin_lock_psm(emsf_lock_id sfid);
+ void soft_spin_unlock_psm(emsf_lock_id sfid);
+-
++void soft_spin_lock_nand_psm(emsf_lock_id sfid);
+ void zx_spinlock_init(void __iomem *spinlock_base);
+ int soft_spin_lock_printf(emsf_lock_id sfid);
+
+diff --git a/upstream/linux-5.10/include/linux/soc/zte/spinlock.h b/upstream/linux-5.10/include/linux/soc/zte/spinlock.h
+index 1181933..e5edb44 100755
+--- a/upstream/linux-5.10/include/linux/soc/zte/spinlock.h
++++ b/upstream/linux-5.10/include/linux/soc/zte/spinlock.h
+@@ -107,7 +107,7 @@
+ void reg_spin_unlock(void);
+ void soft_spin_lock_psm(emsf_lock_id sfid);
+ void soft_spin_unlock_psm(emsf_lock_id sfid);
+-
++void soft_spin_lock_nand_psm(emsf_lock_id sfid);
+ void zx_spinlock_init(void __iomem *spinlock_base);
+ int soft_spin_lock_printf(emsf_lock_id sfid);
+
+diff --git a/upstream/linux-5.10/include/linux/volte_drv.h b/upstream/linux-5.10/include/linux/volte_drv.h
+new file mode 100755
+index 0000000..7862449
+--- /dev/null
++++ b/upstream/linux-5.10/include/linux/volte_drv.h
+@@ -0,0 +1,154 @@
++/*
++ * Copyright (C) 2013 ZTE, China
++ *
++ * It has the ioctl definitions for the volte driver that
++ * userspace needs to know about.
++ */
++
++#ifndef __LINUX_VOLTE_DRV_H
++#define __LINUX_VOLTE_DRV_H
++
++#include <linux/ioctl.h>
++#include <linux/types.h>
++
++
++
++typedef enum {
++ VOICE_GSM_MODE = 0,
++ VOICE_TD_MODE ,
++ VOICE_WCDMA_MODE,
++ VOICE_LTE_MODE,
++ VOICE_GSM_TD_MODE,//GSM TD share
++ VOICE_GSM_WCDMA_MODE, //GSM WCDMA share
++ MAX_VOICE_MODE
++} T_ZDrvVoice_MODE;
++typedef struct {
++ uint32_t clock_rate;
++ uint32_t channel_count;
++ uint32_t samples_per_frame;
++ uint32_t bits_per_sample;
++ uint32_t mode;
++} T_ZDrvVoice_Cfg;
++
++typedef T_ZDrvVoice_Cfg T_ZDrvVolte_Cfg;
++
++#ifdef __KERNEL__
++struct volte_dev {
++ T_ZDrvVoice_Cfg param;
++ void *readbuf;
++ void *writebuf;
++};
++#endif
++
++#define VOLTE_IOCTL_READ_START _IO('v', 1)
++#define VOLTE_IOCTL_READ_STOP _IO('v', 2)
++#define VOLTE_IOCTL_WRITE_START _IO('v', 3)
++#define VOLTE_IOCTL_WRITE_STOP _IO('v', 4)
++#define VOLTE_IOCTL_SET_CFG _IOW('v', 5, T_ZDrvVoice_Cfg)
++#define VOLTE_IOCTL_GET_SLIC_USE_FLAG _IOR ('v', 6, int)
++
++/**************voice define****************/
++typedef enum {
++ AMR_NB_CODEC = 0,
++ AMR_WB_CODEC,
++
++ MAX_CODEC_TYPE
++} T_Codec_Type;
++
++typedef enum {
++ DSP_PATH = 0,
++ SOFT_PATH,
++ MAX_CODEC_PATH
++} T_Codec_Path;
++
++typedef enum {
++ NOR_VOICE_INF_MODE = 0,//normal
++ VB_VOICE_INF_MODE,//voice buffer
++ MAX_VOICE_INF_MODE
++} T_VoiceInfMode;
++
++
++typedef enum {
++ VOICE_STOP = 0,
++ VOICE_START,
++ MAX_VOICE_STATE
++} T_Voice_State;
++
++typedef struct {
++ uint32_t clock_rate; //8000;16000
++ uint32_t mode; //// 0 gsm;1 td;2 wcdma;3 lte
++ uint32_t codec_type;//0 amr-nb;1 amr-wb
++ uint32_t codec_path;//0 hardware dsp;1 soft amr lib
++
++
++} T_Voice_Para;
++
++typedef struct {
++ uint32_t fs; //8000;16000
++ uint32_t enable; //// 0 disable;1 enable
++ uint32_t type;//0 single core;1 mult core
++
++
++} T_VoiceBuf_Para;
++
++
++#ifdef __KERNEL__
++struct voice_dev {
++ T_Voice_Para param;
++ uint32_t voice_state;
++};
++#endif
++
++#define VOICE_IOCTL_START _IOW('v', 10, T_ZDrvVoice_Cfg)
++#define VOICE_IOCTL_STOP _IOW('v', 11, T_ZDrvVoice_Cfg)
++#define VOICE_IOCTL_GET_SLIC_USE_FLAG _IOR ('v', 12, int)
++#define VOICE_IOCTL_VPLOOP _IOW('v', 13, int)
++
++#define VOICE_IOCTL_SET_VOL _IOW('v', 14, int)
++#define VOICE_IOCTL_GET_VOL _IOR('v', 15, int)
++
++#define VOICE_IOCTL_SET_MUTE _IOW('v', 16, bool)
++#define VOICE_IOCTL_GET_MUTE _IOR('v', 17, bool)
++
++#define VOICE_IOCTL_SET_PATH _IOW('v', 18, int)
++#define VOICE_IOCTL_GET_PATH _IOR('v', 19, int)
++
++#define VOICE_IOCTL_GET_FS _IOR('v', 20, int)
++#define VOICE_IOCTL_SET_VOICE_NVRW _IOW('v', 21, int)
++
++#define VOICE_IOCTL_SET_VP _IOW('v', 22, int)
++#define VOICE_IOCTL_GET_VP _IOR('v', 23, int)
++
++#define VOICE_IOCTL_SET_VBUF _IOW('v', 24, T_VoiceBuf_Para)
++#define VOICE_IOCTL_GET_VBUF _IOR('v', 25, T_VoiceBuf_Para)
++
++#define VOICE_IOCTL_SET_INF_MODE _IOW('v', 26, int)
++#define VOICE_IOCTL_GET_INF_MODE _IOR('v', 27, int)
++
++
++
++#ifdef __KERNEL__
++#define print_audio(fmt, ...) \
++ printk(fmt, ##__VA_ARGS__)
++#endif
++
++/**************audiomix define****************/
++typedef struct {
++ uint32_t sample_rate;
++ uint32_t audioType;
++ //uint32_t samples_per_frame;
++ //uint32_t bits_per_sample;
++} T_ZDrvAudioMix_Cfg;
++
++#ifdef __KERNEL__
++struct audio_mix_dev {
++ T_ZDrvAudioMix_Cfg param;
++ //void *readbuf;
++ void *writebuf;
++};
++#endif
++
++#define AUDIOMIX_IOCTL_SET_CFG _IOW('v', 7, T_ZDrvAudioMix_Cfg)
++
++#endif
++
+diff --git a/upstream/linux-5.10/include/net/SI/netioc_proc.h b/upstream/linux-5.10/include/net/SI/netioc_proc.h
+index f0c8aa4..38f9bce 100755
+--- a/upstream/linux-5.10/include/net/SI/netioc_proc.h
++++ b/upstream/linux-5.10/include/net/SI/netioc_proc.h
+@@ -417,6 +417,9 @@
+ extern int fast_local4_output_num; //±¾µØfast_local4³É¹¦·¢Ëͱ¨ÎÄ
+ extern int fast_local6_output_num; //±¾µØfast_local6³É¹¦·¢Ëͱ¨ÎÄ
+ extern int fast_tcpdump_num; //fast×¥°üÊýÁ¿
++extern int skb_expand4; //Í·¿Õ¼ä²»¹»ÖØÐÂÉêÇëµÄV4Êý¾Ý°ü
++extern int skb_expand6; //Í·¿Õ¼ä²»¹»ÖØÐÂÉêÇëµÄV6Êý¾Ý°ü
++
+
+ extern int double_mac;
+
+diff --git a/upstream/linux-5.10/include/net/netfilter/nf_conntrack.h b/upstream/linux-5.10/include/net/netfilter/nf_conntrack.h
+index 04ab917..ff7b8ea 100755
+--- a/upstream/linux-5.10/include/net/netfilter/nf_conntrack.h
++++ b/upstream/linux-5.10/include/net/netfilter/nf_conntrack.h
+@@ -131,6 +131,7 @@
+ struct conn_skbinfo packet_info[IP_CT_DIR_MAX];
+ struct net_device* indev[IP_CT_DIR_MAX];
+ struct net_device* outdev[IP_CT_DIR_MAX];
++ void *fast_entry;
+ };
+
+ static inline struct nf_conn *
+diff --git a/upstream/linux-5.10/init/main.c b/upstream/linux-5.10/init/main.c
+index 83d93ea..576e168 100755
+--- a/upstream/linux-5.10/init/main.c
++++ b/upstream/linux-5.10/init/main.c
+@@ -852,7 +852,7 @@
+ }
+
+ void __weak early_drv_init(void) {}
+-
++void __weak early_debug_info_init(void){}
+ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
+ {
+ char *command_line;
+@@ -950,7 +950,7 @@
+ initcall_debug_enable();
+
+ context_tracking_init();
+-
++ early_debug_info_init();
+ early_drv_init();
+
+ /* init some links before init_ISA_irqs() */
+diff --git a/upstream/linux-5.10/kernel/ramdump/ramdump_device_trans.c b/upstream/linux-5.10/kernel/ramdump/ramdump_device_trans.c
+index 40c920d..f3e91e9 100755
+--- a/upstream/linux-5.10/kernel/ramdump/ramdump_device_trans.c
++++ b/upstream/linux-5.10/kernel/ramdump/ramdump_device_trans.c
+@@ -620,6 +620,8 @@
+ /* interactive begin */
+ if(ramdump_device_init() < 0)
+ return;
++
++ ramdump_device_write_logbuf();
+ data_trans_max = RAMDUMP_SHARED_MEM_LEN - roundup(sizeof(ramdump_shmem_t), RAMDUMP_SHMEM_ALIGN_SIZE) - RAMDUMP_COMPRESS_OUT_LEN;
+ cap_to_server_msg.cmd = RAMDUMP_PC_INTERACTIVE_REQ;
+ ramdump_oss_data_trans_write((unsigned char*)(&cap_to_server_msg), sizeof(cap_to_server_msg));
+@@ -635,8 +637,8 @@
+ ramdump_trans_server_interactive_req *server_to_cap_msg = (ramdump_trans_server_interactive_req *)req_buf;
+ /* data from server to cap */
+ ramdump_file_num = server_to_cap_msg->file_num;
+- ramdump_device_fp.file_num = ramdump_file_num;
+- ramdump_spinand_fp.file_num = ramdump_file_num;
++ ramdump_device_fp.file_num += ramdump_file_num;
++ ramdump_spinand_fp.file_num += ramdump_file_num;
+
+ /* data from cap to server */
+ cap_to_server_msg.cmd = RAMDUMP_PC_FILE_INFO_READ_REQ;
+@@ -732,7 +734,6 @@
+ }
+ case RAMDUMP_TRANS_SERVER_FILE_TRANS_DONE_RSP:
+ {
+- ramdump_device_write_logbuf();
+ ramdump_device_close();
+ return;
+ }
+diff --git a/upstream/linux-5.10/net/8021q/vlan_dev.c b/upstream/linux-5.10/net/8021q/vlan_dev.c
+index 86a1c99..6117e9c 100755
+--- a/upstream/linux-5.10/net/8021q/vlan_dev.c
++++ b/upstream/linux-5.10/net/8021q/vlan_dev.c
+@@ -94,7 +94,7 @@
+ return NETDEV_TX_OK;
+ #endif
+ }
+-
++extern void fast_update_indev(struct sk_buff *skb, struct net_device *dev);
+ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+ {
+@@ -120,7 +120,7 @@
+ len = skb->len;
+ if (unlikely(netpoll_tx_running(dev)))
+ return vlan_netpoll_send_skb(vlan, skb);
+-
++ fast_update_indev(skb, dev);
+ ret = dev_queue_xmit(skb);
+
+ if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
+diff --git a/upstream/linux-5.10/net/bridge/br_fdb.c b/upstream/linux-5.10/net/bridge/br_fdb.c
+index 65a6054..974ee5e 100755
+--- a/upstream/linux-5.10/net/bridge/br_fdb.c
++++ b/upstream/linux-5.10/net/bridge/br_fdb.c
+@@ -1313,7 +1313,7 @@
+ u16 vid = 0;
+ int ntl_port_id = 0xff;
+
+- if(!skb->dev)
++ if(!skb->dev || fastbr_level != 1)
+ {
+ //print_sun(SUN_DBG, "fast_br skb->dev err skb->dev = %x\n", skb->dev);
+ return 0;
+diff --git a/upstream/linux-5.10/net/core/SI/net_other.c b/upstream/linux-5.10/net/core/SI/net_other.c
+index a6748c7..816686b 100755
+--- a/upstream/linux-5.10/net/core/SI/net_other.c
++++ b/upstream/linux-5.10/net/core/SI/net_other.c
+@@ -1090,7 +1090,8 @@
+ int fast_local4_output_num = 0; //±¾µØfast_local4³É¹¦·¢Ëͱ¨ÎÄ
+ int fast_local6_output_num = 0; //±¾µØfast_local6³É¹¦·¢Ëͱ¨ÎÄ
+ int fast_tcpdump_num = 0; //fast×¥°üÊýÁ¿
+-
++int skb_expand4 = 0; //Í·¿Õ¼ä²»¹»ÖØÐÂÉêÇëµÄV4Êý¾Ý°ü
++int skb_expand6 = 0; //Í·¿Õ¼ä²»¹»ÖØÐÂÉêÇëµÄV6Êý¾Ý°ü
+
+ int double_mac = 0; //mac¼ì²é¿ª¹Ø
+ //slabÄÚ´æÊ¹ÓÃÏà¹ØÍ³¼Æ£¬Î´¿¼ÂÇͨÓÃslabµØÖ·³Ø£¬Èçkmalloc
+diff --git a/upstream/linux-5.10/net/core/fastproc/fast4_fw.c b/upstream/linux-5.10/net/core/fastproc/fast4_fw.c
+index 0ef32e4..a0674f9 100755
+--- a/upstream/linux-5.10/net/core/fastproc/fast4_fw.c
++++ b/upstream/linux-5.10/net/core/fastproc/fast4_fw.c
+@@ -67,6 +67,7 @@
+ /* ******************************** º¯ÊýʵÏÖ ********************************/
+ int dst_expire_count = 0;
+ extern int no_neighbour;
++extern fast_list_t working_list;
+
+ static inline int rt_is_expired(struct rtable *rth)
+ {
+@@ -555,7 +556,11 @@
+ {
+ ret = ifname_compare_aligned(ct->indev[dir]->name, ipinfo->iniface, ipinfo->iniface_mask);
+ }
+-
++ else
++ {
++ ret=1;
++ }
++
+ if(ipinfo->iniface[0] != '\0')
+ *match_filter = 1;
+
+@@ -583,6 +588,8 @@
+ ip_packet_match_neg(const struct ipt_ip *ipinfo,struct nf_conn* ct,int dir, int* match_filter)
+ {
+ unsigned long ret;
++ if(!(ct->status & IPS_NAT_MASK))
++ return false;
+ if (NF_INVF(ipinfo, IPT_INV_SRCIP,
+ (ct->tuplehash[dir].tuple.dst.u3.ip & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) ||
+ NF_INVF(ipinfo, IPT_INV_DSTIP,
+@@ -595,7 +602,11 @@
+ {
+ ret = ifname_compare_aligned(ct->outdev[dir]->name, ipinfo->iniface, ipinfo->iniface_mask);
+ }
+-
++ else
++ {
++ ret = 1;
++ }
++
+ if(ipinfo->iniface[0] != '\0')
+ *match_filter = 1;
+
+@@ -675,7 +686,7 @@
+ e = get_entry(table_base, private->hook_entry[NF_INET_LOCAL_IN]);
+ break;
+ default:
+- break;
++ return;
+ }
+ while(num--)
+ {
+@@ -747,8 +758,7 @@
+
+ static void ct_iptables_bhfunc(unsigned long param)
+ {
+- int hash = 0;
+- struct nf_conntrack_tuple_hash *h;
++ fast_entry_t *ret = NULL;
+ struct hlist_nulls_node *n;
+ struct nf_conn *ct;
+ struct xt_table_info *private;
+@@ -756,13 +766,12 @@
+ unsigned int addend;
+ local_bh_disable();
+ addend = xt_write_recseq_begin();
+- for(hash = 0; hash < nf_conntrack_htable_size; hash++)
+- {
+- hlist_nulls_for_each_entry_rcu(h,n,&nf_conntrack_hash[hash],hnnode)
++ spin_lock_bh(&fast_fw_spinlock);
++ for (ret = (&working_list)->next; ret; ret = ret->next)
++ {
++ if(ret)
+ {
+- if(h)
+- {
+- ct = nf_ct_tuplehash_to_ctrack(h);
++ ct = ret->ct;
+ if(ct->fast_ct.isFast)
+ {
+ net = nf_ct_net(ct);
+@@ -777,19 +786,66 @@
+ }
+ else
+ continue;
+- spin_lock_bh(&fast_fw_spinlock);
++
+ ct->packet_info[IP_CT_DIR_ORIGINAL].bytes = 0;
+ ct->packet_info[IP_CT_DIR_ORIGINAL].packets = 0;
+ ct->packet_info[IP_CT_DIR_REPLY].bytes = 0;
+ ct->packet_info[IP_CT_DIR_REPLY].packets = 0;
+- spin_unlock_bh(&fast_fw_spinlock);
+- }
+- }
+- }
++ }
++ }
++ spin_unlock_bh(&fast_fw_spinlock);
+ xt_write_recseq_end(addend);
+ local_bh_enable();
+ }
+
++#if 0
++/*ÐÂfastÏÂiptablesͬ²½µÄ´úÂ루±£Áô£©*/
++/* Started by AICoder, pid:bc328v3b69u30bb14fea08b4d0be594808c2486b */
++static void ct_iptables_bhfunc(unsigned long param)
++{
++ unsigned int addend;
++ local_bh_disable();
++ addend = xt_write_recseq_begin();
++ spin_lock_bh(&fast_fw_spinlock);
++ for(int hash = 0; hash < nf_conntrack_htable_size; hash++)
++ {
++ struct nf_conntrack_tuple_hash *h;
++ struct hlist_nulls_node *n;
++ for_each_rcu_safe(h, n, &nf_conntrack_hash[hash])
++ {
++ if(h)
++ {
++ struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
++ if(ct->fast_ct.isFast)
++ {
++ struct net *net = nf_ct_net(ct);
++ struct xt_table_info *private;
++ const char *chain_names[] = {
++ "IPTABLE_RAW",
++ "IPTABLE_MANGLE",
++ "IPTABLE_NAT",
++ "IPTABLE_FILTER"
++ };
++ for (int i = 0; i < 4; i++) {
++ switch (i) {
++ case 0: private = READ_ONCE(net->ipv4.iptable_raw->private); break;
++ case 1: private = READ_ONCE(net->ipv4.iptable_mangle->private); break;
++ case 2: private = READ_ONCE(net->ipv4.nat_table->private); break;
++ case 3: private = READ_ONCE(net->ipv4.iptable_filter->private); break;
++ }
++ ct_iptables_syn_handle(ct, private, chain_names[i]);
++ }
++ }
++ }
++ }
++ }
++ spin_unlock_bh(&fast_fw_spinlock);
++ xt_write_recseq_end(addend);
++ local_bh_enable();
++}
++/* Ended by AICoder, pid:bc328v3b69u30bb14fea08b4d0be594808c2486b */
++#endif
++
+
+ int fast4_fw_init(void)
+ {
+diff --git a/upstream/linux-5.10/net/core/fastproc/fast6.c b/upstream/linux-5.10/net/core/fastproc/fast6.c
+index d5fab9c..5beebba 100755
+--- a/upstream/linux-5.10/net/core/fastproc/fast6.c
++++ b/upstream/linux-5.10/net/core/fastproc/fast6.c
+@@ -207,7 +207,9 @@
+ __u8 next_hdr = 0;
+ unsigned char *l4head;
+ struct ipv6hdr *ip6;
+-
++ struct sk_buff *skb2 = NULL;
++ int l4_offset = 0;
++
+ print_sun(SUN_DBG, "enter fast_6_recv \n");
+
+ if (fastnat_level == FAST_CLOSE)
+@@ -286,13 +288,18 @@
+ print_sun(SUN_DBG, "fast_6_recv l4head is null \n");
+ return 0;
+ }
+-
+-
+-
+- if (!(skb = fast_expand_headroom_v6(skb, dev))){
++ l4_offset = l4head - skb->data;
++
++ if (!(skb2 = fast_expand_headroom_v6(skb, dev))){
+ rcu_read_unlock();
+ return 1;
+ }
++
++ if(skb2 != skb){
++ l4head = skb2->data + l4_offset;
++ skb = skb2;
++ skb_expand6++;
++ }
+
+ fast_tcpdump(skb);
+
+@@ -316,8 +323,30 @@
+ skb->isFastnat = 1;
+ skb->priority = fast6_entry_data->priority;
+ skb->mark = fast6_entry_data->mark;
+-
+-
++ if (likely(skb_get_nfct(skb) == 0)){
++ skb_set_nfct(skb, (unsigned long)fast6_entry->ct);
++ nf_conntrack_get(&fast6_entry->ct->ct_general);
++ }
++ spin_lock_bh(&fast_fw_spinlock);
++ //»ùÓÚctÁ´½ÓµÄÁ÷Á¿Í³¼Æ --- ͳ¼ÆIP°ü²»ÊÇMAC°ü
++ if (fast6_entry_data->tuplehash.tuple.dst.dir == IP_CT_DIR_ORIGINAL){
++ fast6_entry->ct->packet_info[IP_CT_DIR_ORIGINAL].packets++;
++ fast6_entry->ct->packet_info[IP_CT_DIR_ORIGINAL].bytes += skb->len;
++ if(unlikely(fast6_entry->ct->indev[IP_CT_DIR_ORIGINAL] == NULL))
++ fast6_entry->ct->indev[IP_CT_DIR_ORIGINAL] = skb->indev;
++ if(unlikely(fast6_entry->ct->outdev[IP_CT_DIR_ORIGINAL] == NULL))
++ fast6_entry->ct->outdev[IP_CT_DIR_ORIGINAL] = dev;
++ } else if (fast6_entry_data->tuplehash.tuple.dst.dir == IP_CT_DIR_REPLY){
++ fast6_entry->ct->packet_info[IP_CT_DIR_REPLY].packets++;
++ fast6_entry->ct->packet_info[IP_CT_DIR_REPLY].bytes += skb->len;
++ if(unlikely(fast6_entry->ct->indev[IP_CT_DIR_REPLY] == NULL))
++ fast6_entry->ct->indev[IP_CT_DIR_REPLY] = skb->indev;
++ if(unlikely(fast6_entry->ct->outdev[IP_CT_DIR_REPLY] == NULL))
++ fast6_entry->ct->outdev[IP_CT_DIR_REPLY] = dev;
++ } else {
++ printk("fast6 packet error\n");
++ }
++ spin_unlock_bh(&fast_fw_spinlock);
+ //ÄÚºË×Ô´øµÄ»ùÓÚÁ´½ÓµÄÁ÷Á¿Í³¼Æ
+ struct nf_conn_counter *acct = (struct nf_conn_counter*)nf_conn_acct_find(fast6_entry->ct);
+ if (acct) {
+@@ -348,7 +377,8 @@
+
+ //Ö»Óе±ÓÐMACÍ·Ô¤¸³ÖµÊ±£¬²Å×¼¸³Öµ£¬·ñÔòΪIPÍ·
+ skb_push(skb, ETH_HLEN);
+-
++
++ if (fast6_entry_data->hh_flag)
+ memcpy(skb->data, fast6_entry_data->hh_data, ETH_HLEN);
+ /*¸üÐÂÁ¬½Ó³¬Ê±*/
+ if (IPPROTO_TCP == tuple.dst.protonum)
+@@ -470,12 +500,12 @@
+ return NF_ACCEPT;
+ }
+ _neighbour = dst_neigh_lookup_skb(dst, skb);
+- if(!_neighbour)
+- {
+- return NF_ACCEPT;
++ if(_neighbour == NULL && ((ipv6_addr_type(&ipv6_hdr(skb)->daddr)) == IPV6_ADDR_ANY
++ || ((ipv6_addr_type(&ipv6_hdr(skb)->daddr)) & IPV6_ADDR_LOOPBACK))){
++ return NF_ACCEPT;
+ }
+
+- if (memcmp(_neighbour->ha, zeromac, ETH_ALEN) == 0)
++ if (_neighbour && memcmp(_neighbour->ha, zeromac, ETH_ALEN) == 0)
+ {
+ goto accept;
+ }
+@@ -536,9 +566,10 @@
+ fast6_entry_data = &fast6_entry->data[dir];
+ fast6_entry_data->tuplehash.tuple = ct->tuplehash[dir].tuple;
+
+- memcpy(fast6_entry_data->dmac, _neighbour->ha, ETH_ALEN);
++ //memcpy(fast6_entry_data->dmac, _neighbour->ha, ETH_ALEN);
+ fast6_entry_data->priority = skb->priority;
+ fast6_entry_data->mark = skb->mark;
++ if(fast6_entry_data->outdev == NULL){
+ fast6_entry_data->outdev = out;
+
+ if (!record_MAC_header(working_hash6, ct, fast6_entry, fast6_entry_data, _neighbour, out, htons(ETH_P_IPV6)))
+@@ -546,7 +577,7 @@
+ spin_unlock_bh(&fast6_spinlock);
+ goto accept;
+ }
+-
++ }
+ //´Ë´¦±£Ö¤Õý·´Á½¸ö±ê¼Çλ²»³åÍ»
+ fast6_entry->flags = fast6_entry->flags | (1 << dir);
+
+@@ -563,7 +594,7 @@
+ ct->fast_ct.isFast = FAST_CT_WND6;
+
+ accept:
+-
++ if(_neighbour)
+ neigh_release(_neighbour);
+ return NF_ACCEPT;
+ }
+diff --git a/upstream/linux-5.10/net/core/fastproc/fast6_fw.c b/upstream/linux-5.10/net/core/fastproc/fast6_fw.c
+index 322175b..ec21bc6 100755
+--- a/upstream/linux-5.10/net/core/fastproc/fast6_fw.c
++++ b/upstream/linux-5.10/net/core/fastproc/fast6_fw.c
+@@ -40,8 +40,23 @@
+ #include <net/SI/net_cache.h>
+ #include <net/SI/print_sun.h>
+
++#include <linux/netfilter/xt_tcpudp.h>
++#include <linux/netfilter_ipv6/ip6_tables.h>
++
++
+ MODULE_LICENSE("GPL");
+
++static struct task_struct *ct_ip6tables_syn;
++static struct tasklet_struct ct_ip6tables_bh;
++extern unsigned int ct_iptables_syn_sw;
++enum table6_index {
++ IP6TABLE_RAW,
++ IP6TABLE_MANGLE,
++ IP6TABLE_NAT,
++ IP6TABLE_FILTER
++};
++
++
+ /* ***************** ipv6 ¿ìËÙת·¢Ïà¹Ø±äÁ¿ ************************* */
+
+
+@@ -53,6 +68,7 @@
+
+ int dst_expire_count_v6 = 0;
+ extern int no_neighbour;
++extern fast_list_t working_list6;
+ extern void ntl_ct_set_iw(struct sk_buff *skb, struct nf_conn *ct, int ct_dir);
+ int fast6_fw_recv(struct nf_conn *tmpl,
+ struct sk_buff *skb,
+@@ -163,7 +179,8 @@
+ skb->isFastnat = 1;
+ nf_ct_set(skb, (struct nf_conn *)&ct->ct_general, ctinfo);
+
+-
++ ct->packet_info[dir].packets++;
++ ct->packet_info[dir].bytes += skb->len;
+ //»ùÓÚÍø¿ÚµÄÁ÷Á¿Í³¼Æ --- ²Î¿¼linuxÔÉúµÄÇý¶¯£¬Í³¼ÆµÄ¶¼ÊÇIP°ü³¤¶È
+ if (fastnat_level == FAST_NET_DEVICE)
+ {
+@@ -203,6 +220,17 @@
+ }
+ skb->dev = dev;
+ skb->now_location |= FASTNAT_SUCC;
++
++ if(ct->indev[dir] == NULL && skb->indev != NULL)
++ {
++ ct->indev[dir] = skb->indev;
++ }
++
++ if(ct->outdev[dir] == NULL && skb->dev != NULL)
++ {
++ ct->outdev[dir] = skb->dev;
++ }
++
+ skb->vlan_proto = vlan_proto_raw;
+ skb->vlan_tci = vlan_tci_raw;
+ __flush_dcache_area(skb->data, skb->len);
+@@ -370,6 +398,372 @@
+ .priority = NF_IP6_PRI_LAST,
+ };
+
++static inline bool
++port_match(u_int16_t min, u_int16_t max, u_int16_t port, bool invert)
++{
++ return (port >= min && port <= max) ^ invert;
++}
++
++static bool ctable_mt(struct nf_conn* ct, struct xt_action_param *par,int dir, int* match_filter)
++{
++ const struct xt_tcp *tcpinfo = par->matchinfo;
++
++ if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
++ ntohs(ct->tuplehash[dir].tuple.src.u.tcp.port),
++ !!(tcpinfo->invflags & XT_TCP_INV_SRCPT)))
++ return false;
++ if((tcpinfo->spts[0] || tcpinfo->spts[1]) ^ (!!(tcpinfo->invflags & XT_TCP_INV_SRCPT)))
++ *match_filter = 1;
++ if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
++ ntohs(ct->tuplehash[dir].tuple.dst.u.tcp.port),
++ !!(tcpinfo->invflags & XT_TCP_INV_DSTPT)))
++ return false;
++ if((tcpinfo->dpts[0] || tcpinfo->dpts[1]) ^ (!!(tcpinfo->invflags & XT_TCP_INV_DSTPT)))
++ *match_filter = 1;
++ return true;
++}
++
++static inline bool
++ip6_packet_match(const struct ip6t_ip6 *ip6info,struct nf_conn* ct,int dir, int* match_filter)
++{
++ unsigned long ret;
++ if (NF_INVF(ip6info, IP6T_INV_SRCIP,
++ ipv6_masked_addr_cmp((struct in6_addr *)(ct->tuplehash[dir].tuple.src.u3.ip6), &ip6info->smsk,
++ &ip6info->src)) ||
++ NF_INVF(ip6info, IP6T_INV_DSTIP,
++ ipv6_masked_addr_cmp((struct in6_addr *)(ct->tuplehash[dir].tuple.dst.u3.ip6), &ip6info->dmsk,
++ &ip6info->dst)))
++ return false;
++ if(ip6info->src.in6_u.u6_addr32[0] || ip6info->dst.in6_u.u6_addr32[0])
++ {
++ *match_filter = 1;
++ }
++
++ if(ct->indev[dir] != NULL)
++ {
++ ret = ifname_compare_aligned(ct->indev[dir]->name, ip6info->iniface, ip6info->iniface_mask);
++ }
++ else
++ {
++ ret=1;
++ }
++
++ if(ip6info->iniface[0] != '\0')
++ *match_filter = 1;
++
++ if (NF_INVF(ip6info, IP6T_INV_VIA_IN, ret != 0))
++ return false;
++ if(ct->outdev[dir] != NULL)
++ {
++ ret = ifname_compare_aligned(ct->outdev[dir]->name, ip6info->outiface, ip6info->outiface_mask);
++ }
++
++ if(ip6info->outiface[0] != '\0')
++ *match_filter = 1;
++
++ if (NF_INVF(ip6info, IP6T_INV_VIA_OUT, ret != 0))
++ return false;
++
++ if (ip6info->flags & IP6T_F_PROTO) {
++ int protohdr;
++
++ protohdr = ct->tuplehash[dir].tuple.dst.protonum;
++
++ if (ip6info->proto == protohdr) {
++ if (ip6info->invflags & IP6T_INV_PROTO)
++ return false;
++
++ return true;
++ }
++
++ /* We need match for the '-p all', too! */
++ if ((ip6info->proto != 0) &&
++ !(ip6info->invflags & IP6T_INV_PROTO))
++ return false;
++ }
++
++ return true;
++}
++
++static inline bool
++ip6_packet_match_neg(const struct ip6t_ip6 *ip6info,struct nf_conn* ct,int dir, int* match_filter)
++{
++ unsigned long ret;
++ if(!(ct->status & IPS_NAT_MASK))
++ return false;
++ if (NF_INVF(ip6info, IP6T_INV_SRCIP,
++ ipv6_masked_addr_cmp((struct in6_addr *)ct->tuplehash[dir].tuple.src.u3.ip6, &ip6info->smsk,
++ &ip6info->src)) ||
++ NF_INVF(ip6info, IP6T_INV_DSTIP,
++ ipv6_masked_addr_cmp((struct in6_addr *)ct->tuplehash[dir].tuple.dst.u3.ip6, &ip6info->dmsk,
++ &ip6info->dst)))
++ return false;
++ if(ip6info->src.in6_u.u6_addr32[0] || ip6info->dst.in6_u.u6_addr32[0])
++ *match_filter = 1;
++
++ if(ct->outdev[dir] != NULL)
++ {
++ ret = ifname_compare_aligned(ct->outdev[dir]->name, ip6info->iniface, ip6info->iniface_mask);
++ }
++ else
++ {
++ ret = 1;
++ }
++
++ if(ip6info->iniface[0] != '\0')
++ *match_filter = 1;
++
++ if (NF_INVF(ip6info, IP6T_INV_VIA_IN, ret != 0))
++ return false;
++ if(ct->indev[dir] != NULL)
++ {
++ ret = ifname_compare_aligned(ct->indev[dir]->name, ip6info->outiface, ip6info->outiface_mask);
++ }
++
++ if(ip6info->outiface[0] != '\0')
++ *match_filter = 1;
++
++ if (NF_INVF(ip6info, IP6T_INV_VIA_OUT, ret != 0))
++ return false;
++
++ if (ip6info->flags & IP6T_F_PROTO) {
++ int protohdr;
++
++ protohdr = ct->tuplehash[dir].tuple.dst.protonum;
++
++ if (ip6info->proto == protohdr) {
++ if (ip6info->invflags & IP6T_INV_PROTO)
++ return false;
++
++ return true;
++ }
++
++ /* We need match for the '-p all', too! */
++ if ((ip6info->proto != 0) &&
++ !(ip6info->invflags & IP6T_INV_PROTO))
++ return false;
++ }
++
++ return true;
++}
++
++static inline struct ip6t_entry *
++get_entry(const void *base, unsigned int offset)
++{
++ return (struct ip6t_entry *)(base + offset);
++}
++
++static inline
++struct ip6t_entry *ip6t_next_entry(const struct ip6t_entry *entry)
++{
++ return (void *)entry + entry->next_offset;
++}
++
++
++
++//ͬ²½ctͳ¼ÆÐÅÏ¢µ½iptables,ͬ²½ÖÜÆÚÔݶ¨1s
++static int ct_ip6tables_syn_thread(void *param)
++{
++ while (1)
++ {
++ if(ct_iptables_syn_sw)
++ {
++ rcu_read_lock();
++ tasklet_schedule(&ct_ip6tables_bh);
++ rcu_read_unlock();
++ //ÿ´Îͬ²½¼ä¸ôΪ1s.
++ }
++ msleep(1*1000);
++ }
++ return 0;
++}
++
++void ct_ip6tables_syn_handle(struct nf_conn *ct,struct xt_table_info *private,int table_id)
++{
++ void *table_base;
++ struct ip6t_entry *e;
++ const struct xt_entry_match *ematch;
++ struct xt_action_param acpar;
++ struct xt_counters *counter;
++ int match_flag = 0;
++ int match_filter = 0;
++ int num = 0;
++
++
++ table_base = private->entries;
++ num = private->number;
++ switch(table_id)
++ {
++ case 0:
++ case 1:
++ case 2:
++ e = get_entry(table_base, private->hook_entry[NF_INET_PRE_ROUTING]);
++ break;
++ case 3:
++ e = get_entry(table_base, private->hook_entry[NF_INET_LOCAL_IN]);
++ break;
++ default:
++ return;
++ }
++ while(num--)
++ {
++ match_flag = 0;
++ match_filter = 0;
++ if(!ip6_packet_match(&e->ipv6, ct, IP_CT_DIR_ORIGINAL,&match_filter) &&
++ !ip6_packet_match_neg(&e->ipv6, ct, IP_CT_DIR_REPLY,&match_filter))
++ {
++ }
++ else
++ {
++ xt_ematch_foreach(ematch, e)
++ {
++ acpar.matchinfo = ematch->data;
++ if (!ctable_mt(ct, &acpar, IP_CT_DIR_ORIGINAL,&match_filter))
++ {
++ match_flag = 1;
++ break;
++ }
++ else
++ {
++ }
++ }
++ if(!match_flag)
++ {
++ if(match_filter)
++ {
++ counter = xt_get_this_cpu_counter(&e->counters);
++ ADD_COUNTER(*counter, ct->packet_info[IP_CT_DIR_ORIGINAL].bytes,ct->packet_info[IP_CT_DIR_ORIGINAL].packets);
++ }
++ e = ip6t_next_entry(e);
++ continue;
++ }
++ match_flag = 0;
++ match_filter = 0;
++ }
++
++ if (!ip6_packet_match(&e->ipv6, ct, IP_CT_DIR_REPLY,&match_filter) &&
++ !ip6_packet_match_neg(&e->ipv6, ct, IP_CT_DIR_ORIGINAL,&match_filter))
++ {
++ e = ip6t_next_entry(e);
++ continue;
++ }
++ else
++ {
++ xt_ematch_foreach(ematch, e)
++ {
++ acpar.matchinfo = ematch->data;
++ if (!ctable_mt(ct, &acpar, IP_CT_DIR_REPLY,&match_filter))
++ {
++ match_flag = 1;
++ break;
++ }
++ }
++ if(!match_flag)
++ {
++ if(match_filter)
++ {
++ counter = xt_get_this_cpu_counter(&e->counters);
++ ADD_COUNTER(*counter, ct->packet_info[IP_CT_DIR_REPLY].bytes,ct->packet_info[IP_CT_DIR_REPLY].packets);
++ }
++ e = ip6t_next_entry(e);
++ continue;
++ }
++ }
++ }
++
++}
++
++static void ct_ip6tables_bhfunc(unsigned long param)
++{
++ fast_entry_t *ret = NULL;
++ struct hlist_nulls_node *n;
++ struct nf_conn *ct;
++ struct xt_table_info *private;
++ struct net * net;
++ unsigned int addend;
++ local_bh_disable();
++ addend = xt_write_recseq_begin();
++ spin_lock_bh(&fast_fw_spinlock);
++ for (ret = (&working_list6)->next; ret; ret = ret->next)
++ {
++ if(ret)
++ {
++ ct = ret->ct;
++ if(ct->fast_ct.isFast)
++ {
++ net = nf_ct_net(ct);
++ private = READ_ONCE(net->ipv6.ip6table_raw->private);
++ ct_ip6tables_syn_handle(ct,private,IP6TABLE_RAW);
++ private = READ_ONCE(net->ipv6.ip6table_mangle->private);
++ ct_ip6tables_syn_handle(ct,private,IP6TABLE_MANGLE);
++ private = READ_ONCE(net->ipv6.ip6table_nat->private);
++ ct_ip6tables_syn_handle(ct,private,IP6TABLE_NAT);
++ private = READ_ONCE(net->ipv6.ip6table_filter->private);
++ ct_ip6tables_syn_handle(ct,private,IP6TABLE_FILTER);
++ }
++ else
++ continue;
++
++ ct->packet_info[IP_CT_DIR_ORIGINAL].bytes = 0;
++ ct->packet_info[IP_CT_DIR_ORIGINAL].packets = 0;
++ ct->packet_info[IP_CT_DIR_REPLY].bytes = 0;
++ ct->packet_info[IP_CT_DIR_REPLY].packets = 0;
++ }
++ }
++ spin_unlock_bh(&fast_fw_spinlock);
++ xt_write_recseq_end(addend);
++ local_bh_enable();
++}
++
++#if 0
++/*ÐÂfast ip6tablesÁ÷Á¿Í¬²½´úÂë,±£Áô*/
++/* Started by AICoder, pid:b1b62d7ef7md76714807099a103c224334833109 */
++static void ct_ip6tables_bhfunc(unsigned long param)
++{
++ int hash;
++ struct nf_conn *ct;
++ struct xt_table_info *private;
++ struct net *net;
++ unsigned int addend;
++ local_bh_disable();
++ addend = xt_write_recseq_begin();
++ for(hash = 0; hash < nf_conntrack_htable_size; hash++)
++ {
++ struct nf_conntrack_tuple_hash *h;
++ struct hlist_nulls_node *n;
++ hlist_nulls_for_each_entry_rcu(h, n, &nf_conntrack_hash[hash], hnnode)
++ {
++ if(h)
++ {
++ ct = nf_ct_tuplehash_to_ctrack(h);
++ if(ct->fast_ct.isFast)
++ {
++ net = nf_ct_net(ct);
++ private = READ_ONCE(net->ipv6.ip6table_raw->private);
++ ct_ip6tables_syn_handle(ct, private, IP6TABLE_RAW);
++ private = READ_ONCE(net->ipv6.ip6table_mangle->private);
++ ct_ip6tables_syn_handle(ct, private, IP6TABLE_MANGLE);
++ private = READ_ONCE(net->ipv6.ip6table_nat->private);
++ ct_ip6tables_syn_handle(ct, private, IP6TABLE_NAT);
++ private = READ_ONCE(net->ipv6.ip6table_filter->private);
++ ct_ip6tables_syn_handle(ct, private, IP6TABLE_FILTER);
++ spin_lock_bh(&fast_fw_spinlock);
++ for(int i = 0; i < 4; i++)
++ {
++ ct->packet_info[i].bytes = 0;
++ ct->packet_info[i].packets = 0;
++ }
++ spin_unlock_bh(&fast_fw_spinlock);
++ }
++ }
++ }
++ }
++ xt_write_recseq_end(addend);
++ local_bh_enable();
++}
++/* Ended by AICoder, pid:b1b62d7ef7md76714807099a103c224334833109 */
++#endif
++
+
+ int fast6_fw_init(void)
+ {
+@@ -383,6 +777,14 @@
+ }
+ print_sun(SUN_DBG,"init fast6_fw_init done\n");
+
++ ct_ip6tables_bh.func = ct_ip6tables_bhfunc;
++ ct_ip6tables_syn = kthread_create(ct_ip6tables_syn_thread, (void *)0, "ct_ip6tables_syn" );
++ if (!IS_ERR(ct_ip6tables_syn))
++ {
++ printk("ntl_syn_task thread's init is succ");
++ wake_up_process(ct_ip6tables_syn);
++ }
++
+ return 0;
+ }
+
+@@ -390,6 +792,12 @@
+ {
+ fast_release_all(RELEASE_ALL_DST);
+ nf_unregister_net_hook(&init_net, &fast6_fw_hook);
++ if (ct_ip6tables_syn)
++ {
++ kthread_stop(ct_ip6tables_syn);
++ ct_ip6tables_syn = NULL;
++ }
++ tasklet_kill(&ct_ip6tables_bh);
+ return 0;
+ }
+
+diff --git a/upstream/linux-5.10/net/core/fastproc/fast_common.c b/upstream/linux-5.10/net/core/fastproc/fast_common.c
+index 69f3761..80ad864 100755
+--- a/upstream/linux-5.10/net/core/fastproc/fast_common.c
++++ b/upstream/linux-5.10/net/core/fastproc/fast_common.c
+@@ -621,7 +621,7 @@
+
+ //²Î¿¼ip6_xmit,À©³äskbÍ·²¿
+ struct sk_buff *fast_expand_headroom_v6(struct sk_buff *skb, struct net_device *dev) {
+- unsigned int hh_len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr);
++ unsigned int hh_len = LL_RESERVED_SPACE(dev);//EC616000622279½â¾öv6ÉÏÐÐÊý¾Ý°üÓÉÓÚÍ·¿Õ¼ä²»¹»ÖØÐÂÉêÇëµÄÎÊÌâ + sizeof(struct ipv6hdr);
+ struct sk_buff *skb2 = NULL;
+ if (unlikely(skb_headroom(skb) < hh_len)) {
+ skb2 = skb_realloc_headroom(skb, max(hh_len, NET_SKB_PAD));
+@@ -726,6 +726,9 @@
+ {
+ tcpack_rel(entry);
+ //nf_ct_put(entry->ct);
++ spin_lock_bh(&fast_fw_spinlock);
++ entry->ct->fast_entry = NULL;
++ spin_unlock_bh(&fast_fw_spinlock);
+ atomic_dec(&(entry->ct->ct_general.use));
+ fn_list_del(list_head, entry);
+ }
+@@ -810,6 +813,7 @@
+ netslab_inc(FAST_SLAB);
+ memset(ret, 0, sizeof(fast_entry_t));
+ ret->ct = ct;
++ ct->fast_entry = ret;
+ ret->list_head = list_head;
+
+ //ÉèÖö¨Ê±Æ÷
+@@ -897,7 +901,7 @@
+ goto REL;
+
+ //½ö¶ÔÒÔÌ«ÍøÀàÍø¿Ú½øÐÐMACÍ·Ô¤¸³Öµ£¬ÆäËüµÄÈçPPP¡¢PPPoEÕâЩ£¬½ÔÊǿɱäµÄ£¬²»ÄÜÔ¤¸³Öµ£»²Î¼ûalloc_netdevºÍalloc_etherdev½Ó¿Ú
+- if (out->type != ARPHRD_ETHER)
++ if (out->type != ARPHRD_ETHER || neigh == NULL)
+ return 1;
+
+ //¶ÔÓÚ³ö¿ÚÎªÍøÇÅbrʱ£¬Ö±½Ó»ñÈ¡L2ÍøÂçÉ豸£¬¼´usb0»òwifi0
+@@ -906,7 +910,7 @@
+ if(out->dev_addr == NULL)
+ goto REL;
+
+- if (fastbr_level == 1)
++ if (fastbr_level)
+ {
+ dst_out = getbrport_bydst(out, neigh->ha);
+ if (dst_out == NULL)
+@@ -964,6 +968,9 @@
+ //»Ö¸´ctµÄ³¬Ê±
+ //add_timer(&ct->timeout);
+ //nf_ct_put(ct);
++ spin_lock_bh(&fast_fw_spinlock);
++ entry->ct->fast_entry = NULL;
++ spin_unlock_bh(&fast_fw_spinlock);
+ atomic_dec(&(ct->ct_general.use));
+ del_timer(&entry->timeout);
+ fn_list_del(entry->list_head, entry);
+@@ -1079,7 +1086,9 @@
+ del_timer(&entry->timeout);
+
+ workinghash_del_node(entry);
+-
++ spin_lock_bh(&fast_fw_spinlock);
++ entry->ct->fast_entry = NULL;
++ spin_unlock_bh(&fast_fw_spinlock);
+ //»Ö¸´ctµÄ³¬Ê±
+ //add_timer(&entry->ct->timeout);
+ fn_list_del(list_head, entry);
+@@ -1552,7 +1561,7 @@
+ return 1;
+ }
+ //vlan
+- else if (next_pro == cpu_to_be16(ETH_P_8021Q))
++ else if (next_pro == cpu_to_be16(ETH_P_8021Q) && fastbr_level == 1)
+ {
+ skb->isvlan = 1;
+ skb_pull(skb, VLAN_HLEN);
+@@ -1591,7 +1600,7 @@
+ //if (((unsigned long)skb->data)%4 != 0)
+ //panic("ERR: fast from dev skb->data%4 != 0");
+
+- if (skb->indev == NULL)
++ if (skb->indev == NULL || is_vlan_dev(skb->dev))
+ skb->indev = skb->dev;
+ //ÐèҪ׼ȷ¶¨Î»µ½IPÍ·£¬ÆÚ¼ä¿ÉÄÜÌø¹ýppp/mac/pppoeµÈ¸÷ÖÖ²ã2Í·²¿
+ if (set_skbdata_toip(skb) == 1 && fast_for_ipdata(skb))
+@@ -2055,6 +2064,21 @@
+ return dst;
+ }
+
++void fast_update_indev(struct sk_buff *skb, struct net_device *dev)
++{
++ if(fastbr_level != 1 && skb->isFastnat == 1){
++ enum ip_conntrack_info ctinfo;
++ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
++
++ if(ct){
++ if(ct->indev[0] == skb->indev && ct->indev[1] == NULL)
++ ct->indev[1] = dev;
++ if(ct->indev[1] == skb->indev && ct->indev[0] == NULL)
++ ct->indev[0] = dev;
++ }
++ }
++}
++
+ /*fast³õʼ»¯*/
+ static int __init
+ tsp_fast_init(void)
+diff --git a/upstream/linux-5.10/net/core/fastproc/fast_track.c b/upstream/linux-5.10/net/core/fastproc/fast_track.c
+index 37f3cfc..712ff6d 100755
+--- a/upstream/linux-5.10/net/core/fastproc/fast_track.c
++++ b/upstream/linux-5.10/net/core/fastproc/fast_track.c
+@@ -234,7 +234,7 @@
+ if (copy_from_user(char_fastbr, buffer, 1))
+ return -EFAULT;
+
+- if (char_fastbr[0] < '0' || char_fastbr[0] > '1')
++ if (char_fastbr[0] < '0' || char_fastbr[0] > '2')
+ return -EINVAL;
+
+ fastbr_level = (int)(char_fastbr[0] - '0');
+@@ -252,8 +252,8 @@
+ {
+ if (*pos == 0)
+ {
+- seq_printf(seq, "fastnat have %d conn!!!\nskb_num4:%d,fastnat_num:%d\n",
+- working_list.count, skb_num4, fastnat_num);
++ seq_printf(seq, "fastnat have %d conn!!!\nskb_num4:%d,fastnat_num:%d,expand_head4:%d\n",
++ working_list.count, skb_num4, fastnat_num, skb_expand4);
+ seq_printf(seq, "fastbr_sum:%d,fastbr_num:%d\n",
+ skb_num4 + skb_num6 + skb_unknown - fastnat_num - fast6_num, fastbr_num);
+
+@@ -399,8 +399,8 @@
+ working_list.count,fastnat_recv_count,fastnat_real_count);
+ seq_printf(seq, "send_2_ps_failed:%u, send_2_usb_failed:%u\n", send_2_ps_failed, send_2_usb_failed);
+ #endif
+- seq_printf(seq, "fast6 have %d conn!!!\nskb_num6:%d,fast6_num:%d\n",
+- working_list6.count, skb_num6, fast6_num);
++ seq_printf(seq, "fast6 have %d conn!!!\nskb_num6:%d,fast6_num:%d,expand_head6:%d\n",
++ working_list6.count, skb_num6, fast6_num, skb_expand6);
+ }
+ return &working_hash6[*pos];
+ }
+@@ -1160,6 +1160,42 @@
+ .proc_write = ct_iptables_syn_set,
+ };
+
++/* Started by AICoder, pid:i2747j1887i1a311479909db709e49391b4455c1 */
++static ssize_t dev_unreg_set(struct file *file, const char __user *buffer, size_t count, loff_t *pos)
++{
++ struct net_device *dev = NULL;
++ size_t size;
++ char dev_name[MAX_NET_DEVICE_NAME_LEN + 1] = {0};
++
++ // Ensure that the string is null-terminated
++ if (count == 0 || count > MAX_NET_DEVICE_NAME_LEN + 1)
++ return -EINVAL;
++
++ // Copy the device name from user space and ensure it's null terminated
++ size = min(count - 1, MAX_NET_DEVICE_NAME_LEN);
++ if (copy_from_user(dev_name, buffer, size)) {
++ return -EFAULT;
++ }
++ dev_name[size] = '\0'; // Ensure null-termination
++
++ // Try to get the network device by name
++ dev = dev_get_by_name(&init_net, dev_name);
++ if (dev) {
++ // Put the device reference
++ dev_put(dev);
++ // Unregister the network device
++ unregister_netdev(dev);
++ } else {
++ printk("dev_unreg %s not found\n", dev_name);
++ }
++
++ return count;
++}
++
++static const struct proc_ops dev_unreg_file_ops = {
++ .proc_write = dev_unreg_set,
++};
++/* Ended by AICoder, pid:i2747j1887i1a311479909db709e49391b4455c1 */
+
+ //¿ìËÙת·¢procÎļþµÄ³õʼ»¯
+ int fast_conntrack_init_proc(void)
+@@ -1195,6 +1231,7 @@
+ proc_create("dev_reset_stats", 0440, init_net.proc_net, &dev_reset_file_ops);
+
+ proc_create("ct_iptables_syn", 0440, init_net.proc_net, &ct_iptables_syn_file_ops);
++ proc_create("dev_unreg", 0440, init_net.proc_net, &dev_unreg_file_ops);
+ return 1;
+ }
+
+diff --git a/upstream/linux-5.10/net/core/fastproc/fastnat.c b/upstream/linux-5.10/net/core/fastproc/fastnat.c
+index 717454c..8d585c0 100755
+--- a/upstream/linux-5.10/net/core/fastproc/fastnat.c
++++ b/upstream/linux-5.10/net/core/fastproc/fastnat.c
+@@ -209,6 +209,7 @@
+ {
+ iph = (struct iphdr *)skb2->data;
+ skb = skb2;
++ skb_expand4++;
+ }
+
+ fast_tcpdump(skb);
+@@ -275,7 +276,8 @@
+
+ skb->priority = nat_entry_data->priority;
+ skb->mark = nat_entry_data->mark;
+-
++
++ spin_lock_bh(&fast_fw_spinlock);
+ //»ùÓÚctÁ´½ÓµÄÁ÷Á¿Í³¼Æ --- ͳ¼ÆIP°ü²»ÊÇMAC°ü
+ if (nat_entry_data->tuplehash.tuple.dst.dir == IP_CT_DIR_ORIGINAL){
+ nat_entry->ct->packet_info[IP_CT_DIR_ORIGINAL].packets++;
+@@ -294,6 +296,7 @@
+ } else {
+ printk("fastnat packet error\n");
+ }
++ spin_unlock_bh(&fast_fw_spinlock);
+
+ //ÄÚºË×Ô´øµÄ»ùÓÚÁ´½ÓµÄÁ÷Á¿Í³¼Æ
+ struct nf_conn_counter *acct = (struct nf_conn_counter *)nf_conn_acct_find((const struct nf_conn *)nat_entry->ct);
+@@ -450,7 +453,8 @@
+ }
+
+ //¹ã²¥¡¢×é²¥²»½¨Á´
+- if (ipv4_is_multicast(ip_hdr(skb)->daddr) || ipv4_is_lbcast(ip_hdr(skb)->daddr))
++ if (ipv4_is_multicast(ip_hdr(skb)->daddr) || ipv4_is_lbcast(ip_hdr(skb)->daddr)
++ || ip_hdr(skb)->daddr == 0 || ip_hdr(skb)->saddr == 0)
+ {
+ return NF_ACCEPT;
+ }
+@@ -467,13 +471,10 @@
+ }
+
+ _neighbour = dst_neigh_lookup_skb(dst, skb);
+- if (!_neighbour)
+- {
+- print_sun(SUN_DBG,"napt_handle() _neighbour = null\n");
++ if(_neighbour == NULL && ((ip_hdr(skb)->daddr & 0xff000000) == 0xff000000 )){
+ return NF_ACCEPT;
+- }
+-
+- if (memcmp(_neighbour->ha, zeromac, ETH_ALEN) == 0)
++ }
++ if (_neighbour && memcmp(_neighbour->ha, zeromac, ETH_ALEN) == 0)
+ {
+ if (strncmp(out->name, ppp_name, strlen(ppp_name)) != 0)
+ {
+@@ -557,9 +558,10 @@
+
+ entry_data = &nat_entry->data[dir];
+ entry_data->tuplehash.tuple = ct->tuplehash[dir].tuple;
+- memcpy(entry_data->dmac, _neighbour->ha, ETH_ALEN);
++ //memcpy(entry_data->dmac, _neighbour->ha, ETH_ALEN);
+ entry_data->priority = skb->priority;
+ entry_data->mark = skb->mark;
++ if(entry_data->outdev == NULL){
+ entry_data->outdev = out;
+
+ /*¼Ç¼MACµØÖ·µ½entry_data->hh_data*/
+@@ -568,6 +570,7 @@
+ spin_unlock_bh(&fastnat_spinlock);
+ goto accept;
+ }
++ }
+ print_sun(SUN_DBG,"napt_handle() ct->status=0x%x\n", ct->status);
+ /*»ñÈ¡natת»»ÐèÒªµÄIPºÍportÐÅÏ¢*/
+ if (test_bit(IPS_SRC_NAT_BIT, &ct->status))
+@@ -624,6 +627,7 @@
+ spin_unlock_bh(&fastnat_spinlock);
+
+ accept:
++ if(_neighbour)
+ neigh_release(_neighbour);
+ return NF_ACCEPT;
+ }
+diff --git a/upstream/linux-5.10/net/netfilter/nf_conntrack_core.c b/upstream/linux-5.10/net/netfilter/nf_conntrack_core.c
+index e92413e..d4ae0b7 100755
+--- a/upstream/linux-5.10/net/netfilter/nf_conntrack_core.c
++++ b/upstream/linux-5.10/net/netfilter/nf_conntrack_core.c
+@@ -1621,6 +1621,11 @@
+ ct->packet_info[IP_CT_DIR_ORIGINAL].bytes = 0;
+ ct->packet_info[IP_CT_DIR_REPLY].packets = 0;
+ ct->packet_info[IP_CT_DIR_REPLY].bytes = 0;
++ ct->indev[IP_CT_DIR_ORIGINAL] = NULL;
++ ct->outdev[IP_CT_DIR_ORIGINAL] = NULL;
++ ct->indev[IP_CT_DIR_REPLY] = NULL;
++ ct->outdev[IP_CT_DIR_REPLY] = NULL;
++ ct->fast_entry = NULL;
+ for(dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++)
+ {
+ ct->indev[dir] = NULL;
+diff --git a/upstream/linux-5.10/sound/soc/codecs/es8311.c b/upstream/linux-5.10/sound/soc/codecs/es8311.c
+index fef445f..34410ce 100755
+--- a/upstream/linux-5.10/sound/soc/codecs/es8311.c
++++ b/upstream/linux-5.10/sound/soc/codecs/es8311.c
+@@ -766,35 +766,38 @@
+ /* set iface */
+ snd_soc_component_write(component, ES8311_SDPOUT_REG0A, iface);
+ }
+-/* yu.dong@20240508[ZXW-277]Modified Platform CODEC ES8311 Compatible with I2S and TDM Modes start */
+-#ifdef CONFIG_USE_TOP_TDM
++/* yu.dong@20240816[ZXW-277]Disable soft ramp, optimize playback 44.1k noise issue start */
++#if defined(CONFIG_USE_TOP_TDM)
++ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG02, 0x1a);
+ #else
+- snd_soc_component_write(component, ES8311_CLK_MANAGER_REG02, 0x98);
++ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG02, 0x98);
++#endif
+ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG03, 0x1b);
+ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG04, 0x1b);
+- /*
++
+ if(rate == 8000){
+- snd_soc_component_write(component, ES8311_CLK_MANAGER_REG05, 0xbb);
+- pr_info("%s rate:%d\n",__FUNCTION__,rate);
+-
+- }
+- if(rate == 16000){
+- snd_soc_component_write(component, ES8311_CLK_MANAGER_REG05, 0x55);
+- pr_info("%s rate:%d\n",__FUNCTION__,rate);
+-
+- }
+- */
+- if(rate == 44100){
+-
+- snd_soc_component_write(component, ES8311_CLK_MANAGER_REG02, 0x90);
+- snd_soc_component_write(component, ES8311_CLK_MANAGER_REG03, 0x1d);
+- snd_soc_component_write(component, ES8311_CLK_MANAGER_REG04, 0x1d);
+- snd_soc_component_write(component, ES8311_CLK_MANAGER_REG05, 0x00);
+- pr_info("%s rate:%d\n",__FUNCTION__,rate);
+-
+- }
++#if defined(CONFIG_USE_TOP_TDM)
++ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG05, 0x00);
++#else
++ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG05, 0xbb);
+ #endif
+-/* yu.dong@20240508[ZXW-277]Modified Platform CODEC ES8311 Compatible with I2S and TDM Modes end */
++ pr_info("%s rate:%d\n",__FUNCTION__,rate);
++
++ }
++
++ if(rate == 16000){
++ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG05, 0x55);
++ pr_info("%s rate:%d\n",__FUNCTION__,rate);
++ }
++
++ if(rate == 44100){
++ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG02, 0x00);
++ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG03, 0x10);
++ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG04, 0x20);
++ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG05, 0x00);
++ pr_info("%s rate:%d\n",__FUNCTION__,rate);
++ }
++/* yu.dong@20240816[ZXW-277]Disable soft ramp, optimize playback 44.1k noise issue end */
+ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG06, 0x18);
+ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG07, 0x06);
+
+@@ -893,7 +896,7 @@
+ snd_soc_component_write(component, ES8311_ADC_REG15, 0x40);
+ snd_soc_component_write(component, ES8311_ADC_REG1B, 0x0A);
+ snd_soc_component_write(component, ES8311_ADC_REG1C, 0x6A);
+- snd_soc_component_write(component, ES8311_DAC_REG37, 0x48);
++ snd_soc_component_write(component, ES8311_DAC_REG37, 0x08); //0 – disable soft ramp
+ /* yu.dong@20240718[ZXW-277]Optimizing Recording in CODEC 8311 TDM Mode start*/
+ #if defined(CONFIG_USE_TOP_TDM)
+ snd_soc_component_write(component, ES8311_CLK_MANAGER_REG01, 0x9f);
+diff --git a/upstream/pub/include/infra/pub_debug_info.h b/upstream/pub/include/infra/pub_debug_info.h
+index 10357aa..95a480f 100755
+--- a/upstream/pub/include/infra/pub_debug_info.h
++++ b/upstream/pub/include/infra/pub_debug_info.h
+@@ -6,62 +6,43 @@
+ #define DEBUG_INFO_DEV_PATH "/dev/debug_info"
+
+ /* AP²àºÍCAP²àµÄPS\KERNEL\DRIVER\FS\APP ÒÔSTART~ENDÎªÇø¼ä£¬¸÷²¿·ÖÔ¤ÁôÁË100¸öID */
+-#define MODULE_ID_PS_START (1)
+-#define MODULE_ID_PS_NAS (1)
+-#define MODULE_ID_PS_RRC (2)
+-#define MODULE_ID_PS_L2 (3)
+-#define MODULE_ID_PS_UICC (99)
+-#define MODULE_ID_PS_END (100)
+
+-#define MODULE_ID_AP_KERNEL_START (101)
+-#define MODULE_ID_AP_KERNEL_END (200)
++#define MODULE_ID_PS_NAS ("ps_nas")
++#define MODULE_ID_PS_RRC ("ps_rrc")
++#define MODULE_ID_PS_L2 ("ps_l2")
++#define MODULE_ID_PS_UICC ("ps_uicc")
++#define MODULE_ID_AP_USB ("ap_usb")
++#define MODULE_ID_AP_REBOOT ("ap_reboot")
++#define MODULE_ID_AP_TSC ("ap_tsc")
++#define MODULE_ID_AP_PSM ("ap_psm")
++#define MODULE_ID_AP_NAND ("ap_nand")
++#define MODULE_ID_AP_MMC ("ap_mmc")
++#define MODULE_ID_AP_WIFI ("ap_wifi")
+
+-#define MODULE_ID_CAP_KERNEL_START (201)
+-#define MODULE_ID_CAP_KERNEL_END (300)
+
+-#define MODULE_ID_AP_DRIVES_START (301)
+-#define MODULE_ID_AP_USB (301)
+-#define MODULE_ID_AP_REBOOT (302)
+-#define MODULE_ID_AP_TSC (303)
+-#define MODULE_ID_AP_PSM (304)
+-#define MODULE_ID_AP_NAND (305)
+-#define MODULE_ID_AP_MMC (306)
+-#define MODULE_ID_AP_WIFI (307)
+-#define MODULE_ID_AP_DRIVES_END (400)
++#define MODULE_ID_CAP_USB ("cap_usb")
++#define MODULE_ID_CAP_TSC ("cap_tsc")
++#define MODULE_ID_CAP_PSM ("cap_psm")
++#define MODULE_ID_CAP_NAND ("cap_nand")
++#define MODULE_ID_CAP_SPI ("cap_spi")
++#define MODULE_ID_CAP_MMC ("cap_mmc")
++#define MODULE_ID_CAP_UART ("cap_uart")
++#define MODULE_ID_CAP_PM ("cap_pm")
+
+-#define MODULE_ID_CAP_DRIVES_START (401)
+-#define MODULE_ID_CAP_USB (401)
+-#define MODULE_ID_CAP_TSC (402)
+-#define MODULE_ID_CAP_PSM (403)
+-#define MODULE_ID_CAP_NAND (404)
+-#define MODULE_ID_CAP_SPI (405)
+-#define MODULE_ID_CAP_MMC (406)
+-#define MODULE_ID_CAP_UART (407)
+-#define MODULE_ID_CAP_DRIVES_END (500)
+
+-#define MODULE_ID_AP_FS_START (501)
+-#define MODULE_ID_AP_JFFS2 (501)
+-#define MODULE_ID_AP_FS_END (600)
++#define MODULE_ID_AP_JFFS2 ("ap_jffs2")
++#define MODULE_ID_AP_FOTA ("ap_fota")
++#define MODULE_ID_AP_FS_CHECK ("ap_fs_check")
+
+-#define MODULE_ID_CAP_FS_START (601)
+-#define MODULE_ID_CAP_FS_END (700)
+-
+-#define MODULE_ID_AP_APP_START (701)
+-#define MODULE_ID_AP_FOTA (701)
+-#define MODULE_ID_AP_FS_CHECK (702)
+-#define MODULE_ID_AP_APP_END (800)
+-
+-#define MODULE_ID_CAP_APP_START (801)
+-#define MODULE_ID_CAP_FOTA (801)
+-#define MODULE_ID_CAP_FS_CHECK (802)
+-#define MODULE_ID_CAP_APP_END (900)
+-
+-#if defined(_USE_ZXIC_DEBUG_INFO) && !defined(CONFIG_SYSTEM_RECOVERY)
+-int sc_debug_info_vrecord(unsigned int id, const char *format, va_list args);
+-int sc_debug_info_record(unsigned int id, const char *format, ...);
++#define MODULE_ID_CAP_FOTA ("cap_fota")
++#define MODULE_ID_CAP_FS_CHECK ("cap_fs_check")
++
++#if defined(_USE_ZXIC_DEBUG_INFO)
++int sc_debug_info_vrecord(char *id, const char *format, va_list args);
++int sc_debug_info_record(char *id, const char *format, ...);
+ #else
+-static inline int sc_debug_info_vrecord(unsigned int id, const char *format, va_list args) { return 0; }
+-static inline int sc_debug_info_record(unsigned int id, const char *format, ...) { return 0; }
++static inline int sc_debug_info_vrecord(char *id, const char *format, va_list args) { return 0; }
++static inline int sc_debug_info_record(char *id, const char *format, ...) { return 0; }
+ #endif
+
+ #endif
+\ No newline at end of file
+diff --git a/upstream/pub/include/ps_phy/atipsevent.h b/upstream/pub/include/ps_phy/atipsevent.h
+index 2bd5386..92e71e6 100755
+--- a/upstream/pub/include/ps_phy/atipsevent.h
++++ b/upstream/pub/include/ps_phy/atipsevent.h
+@@ -421,6 +421,7 @@
+ #define AP_MMIA_ZCOPS_TEST_CNF_EV (DWORD)(AP_MMIA_MM_RSP_EVENT + 25)
+ #define AP_MMIA_TIMEZONE_IND_EV (DWORD)(AP_MMIA_MM_RSP_EVENT + 26)
+ #define AP_MMIA_ZULRTIND_IND_EV (DWORD)(AP_MMIA_MM_RSP_EVENT + 27)
++#define AP_MMIA_ZPSABNORMAL_IND_EV (DWORD)(AP_MMIA_MM_RSP_EVENT + 28)
+ /* ========================================================================
+ AP-MMIA CCÏà¹Ø²¿·ÖÏûÏ¢ºÅ
+ ======================================================================== */
+diff --git a/upstream/pub/project/zx297520v3/include/drv/NvParam_drv.h b/upstream/pub/project/zx297520v3/include/drv/NvParam_drv.h
+index 66c6f6d..95c3158 100755
+--- a/upstream/pub/project/zx297520v3/include/drv/NvParam_drv.h
++++ b/upstream/pub/project/zx297520v3/include/drv/NvParam_drv.h
+@@ -214,8 +214,10 @@
+ UINT8 isUseTxDtmfDet;
+ UINT8 isUseRxMixData;
+ UINT8 isUseTxMixData;//12
+- UINT8 isUseEcall;
+- UINT8 reserved[19];//32-13
++ UINT8 isUseEcall; //13
++ UINT8 isUseVoiceBuffer; //14 0 not use,1 use
++ UINT8 selVoiceBufferType; //15 0 single core, 1 dual core
++ UINT8 reserved[17];//32-15
+
+ } T_Audio_NvFlag;
+
+diff --git a/upstream/pub/project/zx297520v3/include/infra/ram_base_config_7520v3.h b/upstream/pub/project/zx297520v3/include/infra/ram_base_config_7520v3.h
+index 6a1626d..edb3bfb 100755
+--- a/upstream/pub/project/zx297520v3/include/infra/ram_base_config_7520v3.h
++++ b/upstream/pub/project/zx297520v3/include/infra/ram_base_config_7520v3.h
+@@ -163,7 +163,7 @@
+ #define DDR_BASE_OFF_CAP (DDR_BASE_OFF_CAP_BUF + DDR_BASE_LEN_CAP_BUF)
+
+ /* capºËµÄdtbµØÖ·¹©ubootºËcap kernelʹÓà */
+-#define DDR_BASE_CAP_DTB_ADDR (DDR_BASE_ADDR_CAP_BUF + (0x00100000UL>>CPU_SHIFT))
++#define DDR_BASE_CAP_DTB_ADDR (DDR_BASE_ADDR_CAP_BUF + (0x00194000UL>>CPU_SHIFT))
+ #else
+ /* 42.75M£¬AP¹²ºË°æ±¾(´Ë´óСÊǰ´ÕÕº¬CAPºËµÄ64MÄÚ´æÅäÖö¨Ò壬¸Ãºê±ð´¦²»»á±»Ê¹ÓÃ) */
+ #define DDR_BASE_ADDR_AP (DDR_BASE_ADDR_RAMDUMP + DDR_BASE_LEN_RAMDUMP)
+@@ -253,6 +253,13 @@
+ #define TEE_SHARE_BUF_ADDR (RAMDUMP_AP_TO_CAP_BUF_ADDR + RAMDUMP_AP_TO_CAP_BUF_LEN)
+ #define TEE_SHARE_BUF_LEN ((384 * 1024UL)>>CPU_SHIFT)
+
++/* psά²â¿Õ¼ä(Êý¾Ý + ¿ØÖÆ)¸´ÓÃAP_TO_CAPµÄramdump´æ´¢¿Õ¼ä */
++#define PS_DEBUG_INFO_LEN_ADDR (RAMDUMP_AP_TO_CAP_BUF_ADDR + ((4 * 1024UL)>>CPU_SHIFT))
++#define PS_DEBUG_INFO_LEN_SIZE ((4 * 1024UL)>>CPU_SHIFT)
++
++#define PS_DEBUG_INFO_ADDR (PS_DEBUG_INFO_LEN_ADDR + PS_DEBUG_INFO_LEN_SIZE)
++#define PS_DEBUG_INFO_SIZE ((64 * 1024UL)>>CPU_SHIFT)
++
+ #define ICP_CAP_BUF_ADDR_PA DDR_BASE_CAPBUF_ADDR_PA
+ #define TOOL_CAP_BUF_ADDR_PA (ICP_CAP_BUF_ADDR_PA + ICP_CAP_BUF_LEN)
+ #define RINGBUF_CAP_TO_AP_ADDR_PA (TOOL_CAP_BUF_ADDR_PA + TOOL_CAP_BUF_LEN)
+@@ -262,6 +269,9 @@
+ #define TOOL_ZSP_TO_CAP_LOG_ADDR_PA (RINGBUF_AP_TO_CAP_ADDR_PA + RINGBUF_AP_TO_CAP_LEN)
+ #define RAMDUMP_AP_TO_CAP_BUF_ADDR_PA (TOOL_ZSP_TO_CAP_LOG_ADDR_PA + TOOL_ZSP_TO_CAP_LOG_LEN)
+ #define TEE_SHARE_BUF_ADDR_PA (RAMDUMP_AP_TO_CAP_BUF_ADDR_PA + RAMDUMP_AP_TO_CAP_BUF_LEN)
++
++#define PS_DEBUG_INFO_LEN_ADDR_PA (RAMDUMP_AP_TO_CAP_BUF_ADDR_PA + ((4 * 1024UL)>>CPU_SHIFT))
++#define PS_DEBUG_INFO_ADDR_PA (PS_DEBUG_INFO_LEN_ADDR_PA + PS_DEBUG_INFO_LEN_SIZE)
+ #endif
+
+ /* 7520V3оƬIRAM0ѹËõ£¬ÐÒéÕ»ÎïÀí²ã½»»¥¿Õ¼äÒÆ¶¯µ½DDR£¬¸´ÓÃRamdump¿Õ¼ä */
+diff --git a/upstream/tools/SignTool/SignImage b/upstream/tools/SignTool/SignImage
+index 552a4de..0b03078 100755
+--- a/upstream/tools/SignTool/SignImage
++++ b/upstream/tools/SignTool/SignImage
+Binary files differ
+diff --git a/upstream/tools/SignTool/SignImage.exe b/upstream/tools/SignTool/SignImage.exe
+index 6905638..7a58d11 100755
+--- a/upstream/tools/SignTool/SignImage.exe
++++ b/upstream/tools/SignTool/SignImage.exe
+Binary files differ
+diff --git a/upstream/tools/SignTool/private.k b/upstream/tools/SignTool/private.k
+new file mode 100755
+index 0000000..9b72371
+--- /dev/null
++++ b/upstream/tools/SignTool/private.k
+Binary files differ